public function getConstructorArgs() { $constructorArgs = parent::getConstructorArgs(); if (isset($constructorArgs['meta']) && empty($constructorArgs['meta'])) { unset($constructorArgs['meta']); } if (isset($constructorArgs['extends'])) { if (StringHelper::isEmpty($constructorArgs['extends']) || Model::isModelBase($constructorArgs['extends'])) { unset($constructorArgs['extends']); } else { $constructorArgs['extends'] = ClassHelper::getNameFromNs($constructorArgs['extends'], BaseOrm::getModelsNamespace()); } } return $constructorArgs; }
public function registerModel(Model $model) { $name = ClassHelper::getNameFromNs($model->meta->modelName, BaseOrm::getModelsNamespace()); if (!ArrayHelper::hasKey($this->allModels, $name)) { $this->allModels[$name] = $model; } $this->resolvePendingOps($model); }
/** * {@inheritdoc} */ public function getConstructorArgs() { $kwargs = parent::getConstructorArgs(); if (ArrayHelper::hasKey($kwargs, 'onDelete')) { $kwargs['onDelete'] = $this->relation->onDelete; } if (is_string($this->relation->toModel)) { $kwargs['to'] = $this->relation->toModel; } else { $name = $this->relation->toModel->getFullClassName(); $kwargs['to'] = ClassHelper::getNameFromNs($name, BaseOrm::getModelsNamespace()); } if ($this->relation->parentLink) { $kwargs['parentLink'] = $this->relation->parentLink; } return $kwargs; }
/** * Gets information about a model and all its parent. * * Some fact to check for : * - proxy model should have at least one concrete model. * - proxy model should not extend an abstract class that contains fields. * * returns the concrete model in the hierarchy and the fields in each of the models in the hierarchy. * * @param string $method the method to invoke * @param null $args the arguments to pass to the method * @param bool|true $fromOldest do we traverse from BaseObject to the child model * * @return array * * @throws TypeError * @throws FieldError * * @since 1.1.0 * * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**> */ private function getHierarchyMeta($method = 'unboundFields', $args = null, $fromOldest = true) { $modelNamespace = BaseOrm::getModelsNamespace(); $isProxy = $this->meta->proxy; // start from oldest parent e.g BaseObject to the last child model $parents = $this->getParents([\PModel::getFullClassName(), self::getFullClassName()]); $parents = array_merge([$this->getFullClassName() => new \ReflectionObject($this)], $parents); if ($fromOldest) { $parents = array_reverse($parents); } $modelFields = []; $concreteParent = null; $immediateParent = null; $previousAbstractParent = null; /** @var $reflectionParent \ReflectionClass */ /* @var $concreteParent \ReflectionClass */ foreach ($parents as $index => $reflectionParent) { $parentName = $reflectionParent->getName(); $isOnCurrentModel = $this->getFullClassName() === $parentName; if (!$reflectionParent->hasMethod($method) || $reflectionParent->getMethod($method)->isAbstract()) { continue; } // concrete is a class that can be instantiated. // check for at least one concrete parent nearest to the last child model. // since we are going downwards we keep updating the concrete variable. if (!($isOnCurrentModel && $isProxy) && $reflectionParent->isInstantiable()) { $concreteParent = $reflectionParent; } // ************ get the fields ******************* // we need to call the parent version of the method for each class to get its fields // this is how we bypass the overriding functionality of php, otherwise if we don't do this the $method will // always provide the fields defined in the last child class. $parentMethodCall = sprintf('%1$s::%2$s', $parentName, $method); if ($args != null) { if (is_array($args)) { $fields = call_user_func_array([$this, $parentMethodCall], $args); } else { $fields = call_user_func([$this, $parentMethodCall], $args); } } else { $fields = call_user_func([$this, $parentMethodCall]); } // =========================== Some Validations ======================== /* * confirm fields with same name don't exist on the parents and current model. * i choose to through an exception of overriding for consistence sake. that is on the $method no overriding * takes place. * */ if ($immediateParent != null && $immediateParent != $previousAbstractParent) { $fieldKeys = array_keys($fields); $parentKeys = isset($modelFields[$immediateParent]) ? array_keys($modelFields[$immediateParent]) : []; $commonFields = array_intersect($parentKeys, $fieldKeys); if (!empty($commonFields)) { throw new FieldError(sprintf('Local field [ %s ] in class "%s" clashes with field of similar name from base class "%s" ', implode(', ', $commonFields), $parentName, $immediateParent)); } } // if the parent is an abstract model and the current model is a proxy model // the parent should not have any fields. abstract models cant have fields // incases where the child is a proxy model if ($isOnCurrentModel && $isProxy && $immediateParent === $previousAbstractParent) { $parentFields = $modelFields[$previousAbstractParent]; if (!empty($parentFields)) { throw new TypeError(sprintf('Abstract base class containing model fields not ' . "permitted for proxy model '%s'.", $parentName)); } } // ****************** Import fields from Abstract *************** // get fields of immediate parent fields if it was an abstract model add them to child model. if (!$isProxy && $previousAbstractParent != null) { $parentFields = isset($modelFields[$previousAbstractParent]) ? $modelFields[$previousAbstractParent] : []; $fields = array_merge($parentFields, $fields); } if ($reflectionParent->isAbstract()) { $previousAbstractParent = $parentName; } else { $previousAbstractParent = null; } if (!$isOnCurrentModel) { $immediateParent = $parentName == $previousAbstractParent ? '' : $parentName; } $modelFields[ClassHelper::getNameFromNs($parentName, $modelNamespace)] = $fields; } if ($isProxy && $concreteParent == null) { throw new TypeError(sprintf("Proxy model '%s' has no non-abstract" . ' model base class.', $this->getShortClassName())); } return [$concreteParent == null ?: ClassHelper::getNameFromNs($concreteParent->getName(), $modelNamespace), $immediateParent, $modelFields]; }
public function getName($name) { return ClassHelper::getNameFromNs($name, BaseOrm::getModelsNamespace()); }
/** * Defines a new model class. * * we create a new namespace and define new classes because, we might be dealing with a model that has been dropped * Meaning if we try to load the model using the normal way, we will get and error of model does not exist. * * @param string $className * @param string $extends * * @return Model * * @since 1.1.0 * * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**> */ private static function createInstance($className, $extends = '') { if (!ClassHelper::classExists($className, BaseOrm::getModelsNamespace())) { MigrationModel::defineClass($className, $extends); } return new $className(); }