Example #1
0
 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;
 }
Example #2
0
 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);
 }
Example #3
0
 /**
  * {@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;
 }
Example #4
0
 /**
  * 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];
 }
Example #5
0
 public function getName($name)
 {
     return ClassHelper::getNameFromNs($name, BaseOrm::getModelsNamespace());
 }
Example #6
0
 /**
  * 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();
 }