Exemple #1
0
 public static function defineClass($className, $extends = '')
 {
     //        $namespace = 'Eddmash\PowerOrm\Migration\Model';
     $namespace = '';
     $use = '';
     $extendedClass = '';
     if (empty($extends) || Model::isModelBase($extends)) {
         $extends = Model::getFullClassName();
     } else {
         $extendedClass = sprintf('%s%s', ClassHelper::getFormatNamespace($namespace, true), $extends);
         $use = sprintf('use %s;', $extendedClass);
         $extends = trim(substr($extends, strripos($extends, '\\')), '\\');
     }
     if (!StringHelper::isEmpty($extendedClass) && !ClassHelper::classExists($extendedClass, $namespace)) {
         self::$deferedClasses[$extends][] = ['class' => $className, 'extends' => $extends];
         return false;
     }
     $extends = ClassHelper::getNameFromNs($extends, $namespace);
     $class = sprintf(self::getTemplate(), $namespace, $use, $className, $extends);
     $className = sprintf('%s%s', ClassHelper::getFormatNamespace($namespace, true), $className);
     if (ArrayHelper::hasKey(self::$deferedClasses, $className)) {
         foreach (self::$deferedClasses[$className] as $deferedClass) {
             self::defineClass($deferedClass['class'], $deferedClass['extends']);
         }
     }
     if (!ClassHelper::classExists($className, $namespace)) {
         eval($class);
     }
     return $className;
 }
Exemple #2
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;
 }
Exemple #3
0
 /**
  * Returns the migration(s) which match the given prefix.
  *
  * @param $prefix
  *
  * @return mixed
  *
  * @throws AmbiguityError
  * @throws KeyError
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 public function getMigrationByPrefix($prefix)
 {
     $migrations = [];
     foreach ($this->getMigrations() as $name => $migration) {
         $shortName = ClassHelper::getNameFromNs($name, BaseOrm::getMigrationsNamespace());
         if (StringHelper::startsWith($name, $prefix) || StringHelper::startsWith($shortName, $prefix)) {
             $migrations[] = $name;
         }
     }
     if (count($migrations) > 1) {
         throw new AmbiguityError(sprintf("There is more than one migration with the prefix '%s'", $prefix));
     } elseif (count($migrations) == 0) {
         throw new KeyError(sprintf("There no migrations with the prefix '%s'", $prefix));
     }
     return $migrations[0];
 }
Exemple #4
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);
 }
Exemple #5
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;
 }
Exemple #6
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];
 }
Exemple #7
0
 public function getName($name)
 {
     return ClassHelper::getNameFromNs($name, BaseOrm::getModelsNamespace());
 }
Exemple #8
0
 /**
  * @dataProvider nameFromNamespaceProvider
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 public function testGettingNameFromNamespace($originalValue, $expectedValue)
 {
     $this->assertEquals($expectedValue, ClassHelper::getNameFromNs($originalValue, '\\app\\model'));
 }
Exemple #9
0
 /**
  * Takes a model returns a ModelState representing it.
  *
  * @param Model      $model
  * @param bool|false $excludeRels
  *
  * @return static
  *
  * @throws TypeError
  *
  * @since 1.1.0
  *
  * @author Eddilbert Macharia (http://eddmash.com) <*****@*****.**>
  */
 public static function fromModel($model, $excludeRels = false)
 {
     $fields = [];
     /** @var $field Field */
     foreach ($model->meta->localFields as $name => $field) {
         try {
             $fields[$name] = $field->deepClone();
         } catch (\Exception $e) {
             throw new TypeError(sprintf("Couldn't reconstruct field %s on %s: %s", $name, $model->meta->modelName));
         }
     }
     if ($excludeRels == false) {
         foreach ($model->meta->localManyToMany as $name => $field) {
             try {
                 $fields[$name] = $field->deepClone();
             } catch (\Exception $e) {
                 throw new TypeError(sprintf("Couldn't reconstruct field %s on %s: %s", $name, $model->meta->modelName));
             }
         }
     }
     $overrides = $model->meta->getOverrides();
     $meta = [];
     $ignore = ['registry'];
     foreach ($overrides as $name => $value) {
         if (in_array($name, $ignore)) {
             continue;
         }
         $meta[$name] = $value;
     }
     $extends = '';
     $parent = $model->getParent();
     if (!$parent->isAbstract() && !Model::isModelBase($parent->getName())) {
         $extends = ClassHelper::getNameFromNs($parent->getName(), BaseOrm::getModelsNamespace());
     }
     $kwargs = ['meta' => $meta, 'extends' => $extends];
     return new static($model->meta->modelName, $fields, $kwargs);
 }