@param      $property
@param null $modelOrRelationName

@return string
553920
protected function buildClause($property, $modelOrRelationName)
    {
        $clause = ucfirst($property);
        if ($modelOrRelationName) {
            $clause = sprintf('%s.%s', ucfirst($modelOrRelationName), $clause);
        }

        return $clause;
    }
454408
public function getRelatedUrl(string $propertyName) : string
    {
        return (!empty($this->relationshipSelfUrl[$propertyName]['related']))
            ? $this->relationshipSelfUrl[$propertyName]['related']
            : '';
    }
215169
private function getRelationValue($property) {
        $propertyName = $property;
        /** @var PersistableObject|PersistableObject[]|scalar|null $value */
        $value = &$this->$propertyName;                                 // existing property value

        if (is_object($value)) return $value;                           // relation is fetched and is an object or an array
        if (is_array ($value)) return $value;                           // (Collections are not yet implemented)

        $dao          =  $this->dao();
        $mapping      =  $dao->getMapping();
        $relation     = &$mapping['relations'][$propertyName];
        $isCollection = strEndsWith($relation['assoc'], 'many');
        /** @var PersistableObject[]|null $emptyResult */
        $emptyResult  = $isCollection ? [] : null;

        if ($value === null) {
            if (!$this->isPersistent())
                return $emptyResult;
        }
        else if ($value === false) {                                    // relation is fetched and marked as empty
            return $emptyResult;
        }

        // The relation is not yet fetched, the property is NULL or holds a physical foreign-key value.
        $type           = $relation['type'];                            // related class name
        /** @var DAO $relatedDao */
        $relatedDao     = $type::dao();
        $relatedMapping = $relatedDao->getMapping();
        $relatedTable   = $relatedMapping['table'];

        if ($value === null) {
            if (isset($relation['column'])) {                           // a local column with a foreign-key value of NULL
                $value = false;
                return $emptyResult;                                    // the relation is marked as empty
            }

            // a local key is used
            if (!isset($relation['key']))
                $relation['key'] = $mapping['identity']['name'];        // default local key is identity
            $keyName = $relation['key'];                                // the used local key property
            if ($this->$keyName === null) {
                $value = false;                                         // the relation is marked as empty
                return $emptyResult;
            }
            $keyColumn = $mapping['properties'][$keyName]['column'];    // the used local key column
            $refColumn = $relation['ref-column'];                       // the referencing column

            if (!isset($relation['join-table'])) {
                // the referencing column is part of the related table
                $refColumnType = $relatedMapping['columns'][$refColumn]['type'];
                $refValue      = $relatedDao->escapeLiteral($this->getPhysicalValue($keyColumn, $refColumnType));
                $sql = 'select r.*
                            from '.$relatedTable.' r
                            where r.'.$refColumn.' = '.$refValue;
            }
            else {
                // the referenced column is part of a join table
                $joinTable = $relation['join-table'];
                $keyValue  = $dao->escapeLiteral($this->getPhysicalValue($keyColumn));  // the physical local key value

                if (!isset($relation['foreign-key']))
                    $relation['foreign-key'] = $relatedMapping['identity']['name'];     // default foreign-key is identity
                $fkName      = $relation['foreign-key'];                                // the used foreign-key property
                $fkColumn    = $relatedMapping['properties'][$fkName]['column'];        // the used foreign-key column
                $fkRefColumn = $relation['fk-ref-column'];                              // join column referencing the foreign-key
                $sql = 'select r.*
                            from '.$relatedTable.' r
                            join '.$joinTable.'    j on r.'.$fkColumn.' = j.'.$fkRefColumn.'
                            where j.'.$refColumn.' = '.$keyValue;
            }
            if ($isCollection) {                                                        // default result sorting
                $relatedIdColumn = $relatedMapping['identity']['column'];               // the related identity column
                $sql .= ' order by r.'.$relatedIdColumn;                                // sort by identity
            }
        }
        else {
            // $value holds a non-NULL column-type foreign-key value pointing to a single related record
            if (isset($relation['join-table'])) {
                if (!isset($relation['foreign-key']))
                    $relation['foreign-key'] = $relatedMapping['identity']['name'];     // default foreign-key is identity
                $fkName   = $relation['foreign-key'];                                   // the used foreign-key property
                $fkColumn = $relatedMapping['properties'][$fkName]['column'];           // the used foreign-key column
            }
            else if (isset($relation['column'])) {                      // a local column referencing the foreign key
                if (!isset($relation['ref-column']))                    // default foreign-key is identity
                    $relation['ref-column'] = $relatedMapping['identity']['column'];
                $fkColumn = $relation['ref-column'];                    // the used foreign-key column
            }
            else {
                $fkColumn = $relatedMapping['identity']['column'];      // the used foreign-key column is identity
            }
            $fkValue = $relatedDao->escapeLiteral($value);
            $sql = 'select r.*
                        from '.$relatedTable.' r
                        where r.'.$fkColumn.' = '.$fkValue;
        }

        if (!$isCollection) $value = $relatedDao->find($sql);           // => PersistableObject
        else                $value = $relatedDao->findAll($sql);        // => PersistableObject[]

        return $value;
    }
1171230
protected function getFieldNameFromData($fieldName, $data, $default = null)
    {
        /*
         * Array field name, eg: field[key][key2][key3]
         */
        $keyParts = HtmlHelper::nameToArray($fieldName);
        $lastField = end($keyParts);
        $result = $data;

        /*
         * Loop the field key parts and build a value.
         * To support relations only the last field should return the
         * relation value, all others will look up the relation object as normal.
         */
        foreach ($keyParts as $key) {

            if ($result instanceof Model && $result->hasRelation($key)) {
                if ($key == $lastField) {
                    $result = $result->getRelationValue($key) ?: $default;
                }
                else {
                    $result = $result->{$key};
                }
            }
            elseif (is_array($result)) {
                if (!array_key_exists($key, $result)) {
                    return $default;
                }
                $result = $result[$key];
            }
            else {
                if (!isset($result->{$key})) {
                    return $default;
                }
                $result = $result->{$key};
            }

        }

        return $result;
    }
1167190
private function getEmbeddedAnnotationData(\ReflectionProperty $property)
    {
        $result = $this->reader->getPropertyAnnotation($property, self::EMBEDDED_ANNOTATION);

        if ($result !== null && $result->name === null) {
            $result->name = Caser::snake($property->getName());
        }

        return $result;
    }
268045
public function getRelation($relation)
    {
        $query = Relation::noConstraints(
            function () use ($relation){
                /** @var BaseModel $model */
                $model = $this->getModel();
                $relationType = $model->getReferencingType($relation);

                if (RelationSchema::HAS_ONE === $relationType) {
                    return $model->getHasOneByRelationName($relation);
                } elseif (RelationSchema::HAS_MANY === $relationType) {
                    return $model->getHasManyByRelationName($relation);
                } elseif (RelationSchema::MANY_MANY === $relationType) {
                    return $model->getBelongsToManyByRelationName($relation);
                } elseif (RelationSchema::BELONGS_TO === $relationType) {
                    return $model->getBelongsToByRelationName($relation);
                }

                return null;
            }
        );

        if (!empty($query)) {
            return $query;
        }

        if (!method_exists($this->getModel(), $relation)) {
            throw new BadRequestException('Unknown relationship: ' . $relation);
        }

        return parent::getRelation($relation);
    }
1114216
public function relation(string $property): RelationUsingDefiner
    {
        $this->verifyProperty(__METHOD__, $property);

        $accessor = new PropertyAccessor($this->class->getClassName(), $this->class->getProperty($property));

        return $this->defineRelationVia($accessor, function () use ($property) {
            $this->mappedProperties[$property] = true;
        });
    }
45705
protected function getModelTpl($modelClassName, $tableName)
    {
        $modelTpl = str_replace(CodeTpl::CLASS_NAME_TAG, $modelClassName, CodeTpl::MODEL_TPL);

        /**
 * @var \PDOStatement $statement 
*/
        $statement = Connection::component()->read_conn->prepare('desc ' . $tableName);
        if ($result = $statement->execute()) {
            $fields = $statement->fetchAll();

            if (!$fields) {
                throw new ParamException(ErrorMsg::INVALID_PARAM);
            }

            //Assemble Attributes & Labels
            $primaryKeyAttr = '';
            $attributes = '';

            $primaryKeyLabel = '';
            $labels = '';

            $primaryKey = '';

            $primaryKeyComment = '';
            $propertyComments = '';

            $setter = '';
            $getter = '';

            foreach ($fields as $field) {
                $attrName = $field['Field'];
                $defaultValue = $this->formatValue($field['Default'], $field['Type']);
                $label = $this->formatLabel($attrName);
                $commentType = $this->getCommentType($field['Type']);
                $camelAttrName = $this->formatAttr($attrName);

                //Setter
                $setter .= <<<EOF
    public function set{$camelAttrName}(\$value)
    {
        \$this->{$attrName} = \$value;
        return \$this;
    }
EOF;
                $setter .= (str_repeat(PHP_EOL, 2));

                //Getter
                $getter .= <<<EOF
    public function get{$camelAttrName}()
    {
        return \$this->{$attrName};
    }
EOF;
                $getter .= (str_repeat(PHP_EOL, 2));

                if ($field['Key'] == 'PRI') {
                    //Primary Key
                    $primaryKey = $attrName;

                    //Primary Key Attribute
                    $primaryKeyAttr = <<<EOF
    '{$attrName}' => {$defaultValue},
EOF;
                    $primaryKeyAttr .= PHP_EOL;

                    //Primary Key Label
                    $primaryKeyLabel = <<<EOF
    '{$attrName}' => '{$label}',
EOF;
                    $primaryKeyLabel .= PHP_EOL;

                    //Primary Key Comment
                    $primaryKeyComment = <<<EOF
 * @property {$commentType} \${$attrName}
EOF;
                    $primaryKeyComment .= PHP_EOL;
                } else {
                    //Attributes
                    $attributes .= <<<EOF
        '{$attrName}' => {$defaultValue},
EOF;
                    $attributes .= PHP_EOL;

                    //Labels
                    $labels .= <<<EOF
        '{$attrName}' => '{$label}',
EOF;
                    $labels .= PHP_EOL;

                    //Property Comment
                    $propertyComments .= <<<EOF
 * @property {$commentType} \${$attrName}
EOF;
                    $propertyComments .= PHP_EOL;
                }
            }
            $modelTpl = str_replace(CodeTpl::ATTRIBUTES_TAG, rtrim($primaryKeyAttr . $attributes, PHP_EOL), $modelTpl);
            $modelTpl = str_replace(CodeTpl::LABELS_TAG, rtrim($primaryKeyLabel . $labels, PHP_EOL), $modelTpl);
            $modelTpl = str_replace(
                CodeTpl::PROPERTY_COMMENTS_TAG,
                rtrim($primaryKeyComment . $propertyComments, PHP_EOL),
                $modelTpl
            );
            $modelTpl = str_replace(CodeTpl::PRIMARY_KEY_TAG, $primaryKey, $modelTpl);
            $modelTpl = str_replace(CodeTpl::SETTER, $setter, $modelTpl);
            $modelTpl = str_replace(CodeTpl::GETTER, rtrim($getter, PHP_EOL), $modelTpl);
        }

        return str_replace(CodeTpl::TABLE_NAME_TAG, $tableName, $modelTpl);
    }
662677
public static function buildSelectRelation($relation, $mapperRelation) {
        $query = "";

        $fields = "";
        foreach ($mapperRelation->getPropertys() as $property) {
            $fields .= "c." . $property->getColumn() . ", ";
        }
        $fields = substr_replace($fields, "", -2);

        if ($relation->getCardinality() == Relation::$manyToMany) {
            $query = "select " . $fields . " from " . $mapperRelation->getTable() . " c ";
            $query .= "inner join " . $relation->getTable() . " nc on nc." . $relation->getForeignColumn() . " = c.id ";
            $query .= "where nc." . $relation->getLocalColumn() . " = :id";
        }
        if ($relation->getCardinality() == Relation::$oneToMany) {
            $query = "select " . $fields . " from " . $mapperRelation->getTable() . " c ";
            $query .= "where c." . $relation->getForeignColumn() . " = :id";
        }
        return $query;
    }
531491
protected function getRelation($name)
    {
        $relation = $this->relations[$name];
        if ($relation instanceof self || (\is_array($relation) && $relation[0] instanceof self)) {
            return $relation;
        }

        $class = 'App\\Model\\' . $relation[1];
        /** @var Model $model */
        $model = new $class();

        switch ($relation[0]) {
            case self::HAS_ONE:
                $this->relations[$name] = $model->eq($relation[2], $this->__get($this->primary))->get();
                break;
            case self::HAS_MANY:
                $this->relations[$name] = $model->eq($relation[2], $this->__get($this->primary))->select();
                break;
            case self::BELONGS_TO:
                $this->relations[$name] = $model->get($this->__get($relation[2]));
                break;
            default:
                throw new ModelException("Relation $name not found.");
        }

        return $this->relations[$name];
    }
549978
private function getPropertyAnnotationData(\ReflectionProperty $property)
    {
        $result = $this->reader->getPropertyAnnotation($property, self::PROPERTY_ANNOTATION);

        if ($result !== null && $result->name === null) {
            $result->name = Caser::snake($property->getName());
        }

        return $result;
    }
1043963
protected function get($property) {
        $mapping = $this->dao()->getMapping();

        if (isset($mapping['properties'][$property]))
            return $this->getNonRelationValue($property);

        if (isset($mapping['relations'][$property]))
            return $this->getRelationValue($property);

        throw new RuntimeException('Not a mapped property "'.$property.'"');
    }
450353
protected function getFieldByProperty($property)
    {
        foreach ($this->getFields() as $key => $annotatedField) {
            if ($property === $key) {
                return $annotatedField;
            }
        }

        return null;
    }
1091179
public static function related_class($relation)
	{
		$class = get_called_class();

		foreach (static::$_valid_relations as $rel_name => $rel_class)
		{
			if (property_exists($class, '_'.$rel_name))
			{
				if (isset(static::${'_'.$rel_name}[$relation]))
				{
					return static::${'_'.$rel_name}[$relation]['model_to'];
				}
			}
		}

		return null;
	}
1139813
public function determineFormStoreStrategy(ModelRelationData $data)
    {
        $type       = null;
        $parameters = [];

        // Determine strategy alias
        switch ($data->type) {

            case RelationType::BELONGS_TO:
            case RelationType::BELONGS_TO_THROUGH:
            case RelationType::MORPH_ONE:
            case RelationType::HAS_ONE:
                $type = FormStoreStrategy::RELATION_SINGLE_KEY;
                break;

            case RelationType::BELONGS_TO_MANY:
            case RelationType::HAS_MANY:
            case RelationType::MORPH_MANY:
            case RelationType::MORPH_TO_MANY:
            case RelationType::MORPHED_BY_MANY:
                $type = FormStoreStrategy::RELATION_PLURAL_KEYS;
                break;

            case RelationType::MORPH_TO:
                $type = FormStoreStrategy::RELATION_SINGLE_MORPH;
                break;
        }


        // Determine parameters

        if ($data->translated) {
            $parameters[] = 'translated';
        }

        if (count($parameters)) {
            $type .= ':' . implode(',', $parameters);
        }

        return $type;
    }
720813
public function renderProperty($model, $property, $view, $form = null)
    {
        return $this->render(
            $this->convertView($view),
            [
                'model' => $model,
                'property' => $property,
                'form' => $form
            ]
        );
    }
431755
public function getRelationLabel($activeRelation, $relation)
    {
        $modelClass = $activeRelation->modelClass;
        if (isset($this->cachedRelationLabels[$modelClass][$relation])) {
            return $this->cachedRelationLabels[$modelClass][$relation];
        }
        if (isset($this->relationLabels[$relation])) {
            $label = $this->relationLabels[$relation];
        } else {
            /** @var ActiveRecord $relationModel */
            $relationModel = new $modelClass;
            $label = $relationModel->getCrudLabel($activeRelation->multiple ? 'relation' : 'default');
        }
        return $this->cachedRelationLabels[$modelClass][$relation] = $label;
    }