Ejemplo n.º 1
0
/**
 * Returns true if an object / class /interface / trait is a class / interface / trait
 *
 * All parent classes, interfaces and traits are scanned recursively
 *
 * @param $object     string|object
 * @param $class_name string|object
 * @return boolean
 */
function isA($object, $class_name)
{
    if (is_string($object)) {
        $object = Builder::className($object);
    } elseif (is_object($object)) {
        $object = get_class($object);
    } else {
        return false;
    }
    if (is_object($class_name)) {
        $class_name = get_class($class_name);
    }
    if (is_a($object, $class_name, true)) {
        return true;
    }
    $classes = class_parents($object) + class_uses($object);
    while ($classes) {
        $next_classes = [];
        foreach ($classes as $class) {
            if (is_a($class, $class_name, true)) {
                return true;
            }
            $next_classes += class_uses($class);
        }
        $classes = $next_classes;
    }
    return false;
}
Ejemplo n.º 2
0
 /**
  * @param $elements Setting[]
  */
 public function __construct($elements = null)
 {
     $settings = [];
     if (isset($elements)) {
         foreach ($elements as $setting) {
             $settings[$setting->code] = $setting;
         }
     }
     parent::__construct(Builder::className('SAF\\Framework\\Setting'), $settings);
 }
Ejemplo n.º 3
0
 /**
  * Apply class name : if constructor was called without columns, this will initialize columns list
  *
  * This applies default column names if there was no default class name, or if class name changed,
  * or if there were no column names.
  *
  * @param $class_name string
  */
 private function applyClassName($class_name)
 {
     if (isset($class_name) && $class_name != $this->class_name && (isset($this->class_name) || !isset($this->columns))) {
         $class_name = Builder::className($class_name);
         $this->class_name = $class_name;
         $columns = (new Reflection_Class($class_name))->getListAnnotation('sort')->values();
         if (!$columns) {
             $columns = (new Reflection_Class($class_name))->getListAnnotation('representative')->values();
         }
         $this->columns = $columns;
         $this->calculateReverse();
     }
 }
Ejemplo n.º 4
0
 /**
  * Apply namespace and use entries to the type name (if class)
  *
  * Return the full element class name, used to modify the type (multiple stays multiple)
  *
  * @param $namespace string
  * @param $use       string[]
  * @return string
  */
 public function applyNamespace($namespace, $use = [])
 {
     /** @var $this Annotation|Types_Annotation */
     /** @var $values string[] */
     $values = is_array($this->value) ? $this->value : [$this->value];
     foreach ($values as $key => $class_name) {
         if (ctype_upper($class_name[0])) {
             if (substr($class_name, -2) == '[]') {
                 $class_name = substr($class_name, 0, -2);
                 $multiple = '[]';
             } else {
                 $multiple = '';
             }
             $values[$key] = Builder::className((new Type($class_name))->applyNamespace($namespace, $use)) . $multiple;
         } elseif ($class_name[0] === BS) {
             $values[$key] = substr($class_name, 1);
         }
     }
     $this->value = is_array($this->value) ? $values : reset($values);
 }
Ejemplo n.º 5
0
 /**
  * @param $source   Reflection_Source the PHP source file object
  * @param $compiler PHP\Compiler the main compiler
  * @return boolean true if compilation process did something, else false
  */
 public function compile(Reflection_Source $source, PHP\Compiler $compiler = null)
 {
     $compiled = false;
     foreach ($source->getClasses() as $class) {
         // replace extends with the built replacement class
         if (!Builder::isBuilt($class->name)) {
             $parent_class_name = $class->getParentName();
             if ($parent_class_name) {
                 $replacement_class_name = Builder::className($parent_class_name);
                 if ($replacement_class_name != $parent_class_name) {
                     $class_exists = class_exists($replacement_class_name, false);
                     if ($class_exists && is_a($replacement_class_name, $parent_class_name) || !$class_exists && Reflection_Source::of($replacement_class_name)->getClass($replacement_class_name)->isA($class->name)) {
                         $replacement_class_name = $parent_class_name;
                     }
                 }
                 if (is_array($replacement_class_name)) {
                     trigger_error("Replacement classes should all be compiled", E_USER_ERROR);
                     $compiler->addSource($source);
                 } elseif ($replacement_class_name !== $parent_class_name && Builder::isBuilt($replacement_class_name)) {
                     $extended = null;
                     $buffer = $source->getSource();
                     $short_class_name = Namespaces::shortClassName($class->name);
                     $buffer = preg_replace_callback('%(\\s+class\\s+' . $short_class_name . '\\s+extends\\s+)([\\\\\\w]+)(\\s+)%', function ($match) use(&$extended, $replacement_class_name) {
                         $extended = $match[2];
                         return $match[1] . BS . $replacement_class_name . $match[3];
                     }, $buffer);
                     if ($extended) {
                         $buffer = preg_replace_callback('%(\\n\\s+\\*\\s+@link\\s+)(' . str_replace(BS, BS . BS, $extended) . ')(\\s+)%', function ($match) use($replacement_class_name) {
                             return $match[1] . BS . $replacement_class_name . $match[3];
                         }, $buffer);
                     }
                     $source->setSource($buffer);
                     $compiled = true;
                 }
             }
         }
     }
     return $compiled;
 }
Ejemplo n.º 6
0
 /**
  * Add a link class (using the 'link' class annotation) to joins
  *
  * @param $path               string     the property path
  * @param $class              Link_Class the link class itself (which contains the @link)
  * @param $linked_class_name  string     the linked class name (the value of @link)
  * @param $join_mode          string
  * @return Reflection_Property[] the properties that come from the linked class,
  * for further exclusion
  */
 private function addLinkedClass($path, $class, $linked_class_name, $join_mode)
 {
     $linked_class = new Reflection_Class($linked_class_name);
     $join = new Join();
     $join->master_alias = 't' . ($this->alias_counter - 1);
     $join->master_column = 'id_' . $class->getCompositeProperty($linked_class_name)->getAnnotation('storage')->value;
     $join->foreign_alias = 't' . $this->alias_counter++;
     $join->foreign_column = 'id';
     $join->foreign_class = Builder::className($linked_class_name);
     $join->foreign_table = Dao::storeNameOf($join->foreign_class);
     $join->mode = $join_mode == Join::LEFT ? Join::LEFT : Join::INNER;
     $join->type = Join::LINK;
     if (!isset($this->joins[$path])) {
         // this ensures that the main path is set before the linked path
         $this->joins[$path] = null;
     }
     $this->joins[($path ? $path . '-' : '') . $join->foreign_table . '-@link'] = $join;
     $this->id_link_joins[$path] = $join;
     $this->link_joins[$path] = $join;
     $more_linked_class_name = $linked_class->getAnnotation('link')->value;
     $exclude_properties = $more_linked_class_name ? $this->addLinkedClass($path, $class, $more_linked_class_name, $join_mode) : [];
     foreach ($linked_class->getProperties([T_EXTENDS, T_USE]) as $property) {
         if (!$property->isStatic()) {
             if (!isset($exclude_properties[$property->name])) {
                 $this->properties[$linked_class_name][$property->name] = $property;
                 $property_path = ($path ? $path . DOT : '') . $property->name;
                 $type = $property->getType();
                 if ($type->isClass()) {
                     $this->classes[$property_path] = $property->getType()->getElementTypeAsString();
                 }
                 $this->link_joins[$property_path] = $join;
                 $exclude_properties[$property->name] = true;
             }
         }
     }
     return $exclude_properties;
 }
Ejemplo n.º 7
0
 /**
  * @param $doc_comment       string
  * @param $annotation_name   string
  * @param $i                 integer
  * @param $annotation_class  string
  * @param $reflection_object Has_Doc_Comment|Reflection
  * @return Annotation
  */
 private static function parseAnnotationValue($doc_comment, $annotation_name, &$i, $annotation_class, Reflection $reflection_object)
 {
     $i += strlen($annotation_name) + 1;
     $next_char = $doc_comment[$i];
     switch ($next_char) {
         case SP:
         case TAB:
             $i++;
             $j = strlen($doc_comment);
             $next_annotation = strpos($doc_comment, SP . '* @', $i);
             $end_doc_comment = strpos($doc_comment, SP . '*/', $i);
             $next_in = strpos($doc_comment, LF . self::DOC_COMMENT_IN, $i);
             if ($next_annotation !== false && $next_annotation < $j) {
                 $j = $next_annotation;
             }
             if ($end_doc_comment !== false && $end_doc_comment < $j) {
                 $j = $end_doc_comment;
             }
             if ($next_in !== false && $next_in < $j) {
                 $j = $next_in;
             }
             if ($j === false) {
                 trigger_error('Missing doc_comment end', E_USER_ERROR);
             }
             $value = trim(preg_replace('%\\s*\\n\\s+\\*\\s*%', '', substr($doc_comment, $i, $j - $i)));
             break;
         case CR:
         case LF:
             $value = true;
             break;
         default:
             $value = null;
     }
     /** @var $annotation Annotation */
     $annotation = isset($value) ? new $annotation_class($value, $reflection_object, $annotation_name) : null;
     if (isset($annotation) && isA($annotation, Annotation_In::class)) {
         /** @var $annotation Annotation_In */
         $j = strrpos(substr($doc_comment, 0, $i), LF . self::DOC_COMMENT_IN);
         if ($j === false) {
             $annotation->class_name = $reflection_object instanceof Reflection_Class_Component ? $reflection_object->getDeclaringClassName() : $reflection_object->getName();
         } else {
             $j += strlen(self::DOC_COMMENT_IN) + 1;
             $k = strpos($doc_comment, LF, $j);
             $annotation->class_name = substr($doc_comment, $j, $k - $j);
         }
     }
     if (isset($annotation) && isA($annotation, Types_Annotation::class)) {
         $do = false;
         if (is_array($annotation->value)) {
             foreach ($annotation->value as $value) {
                 if ($value && (ctype_upper($value[0]) || $value[0] == BS)) {
                     $do = true;
                     break;
                 }
             }
         } else {
             $do = $annotation->value && ctype_upper($annotation->value[0]);
         }
         if ($do) {
             /** @var $annotation Types_Annotation */
             $j = strrpos(substr($doc_comment, 0, $i), LF . self::DOC_COMMENT_IN);
             if ($j === false) {
                 $class_name = $reflection_object instanceof Reflection_Class_Component ? $reflection_object->getDeclaringClassName() : $reflection_object->getName();
                 $namespace = Namespaces::of($class_name);
                 $use = PHP\Reflection_Class::of($class_name)->getNamespaceUse();
             } else {
                 $j += strlen(self::DOC_COMMENT_IN) + 1;
                 $k = strpos($doc_comment, LF, $j);
                 $in_class = substr($doc_comment, $j, $k - $j);
                 $namespace = Namespaces::of($in_class);
                 $use = PHP\Reflection_Class::of($in_class)->getNamespaceUse();
             }
             $annotation->applyNamespace($namespace, $use);
         } elseif (is_array($annotation->value)) {
             foreach ($annotation->value as $key => $value) {
                 $annotation->value[$key] = Builder::className($value);
             }
         } else {
             if ($annotation->value[0] === BS) {
                 $annotation->value = substr($annotation->value, 1);
             }
             $annotation->value = Builder::className($annotation->value);
         }
     }
     return $annotation;
 }
Ejemplo n.º 8
0
 /**
  * @param $property Reflection_Property
  * @return Reflection_Class
  */
 private function getForeignClass(Reflection_Property $property)
 {
     $type = $property->getType();
     $foreign_class_name = Builder::className($type->getElementTypeAsString());
     if ($property instanceof PHP\Reflection_Property) {
         $foreign_class = PHP\Reflection_Class::of($foreign_class_name);
     } else {
         $reflection_class = new Reflection\Reflection_Class(get_class($property->getDeclaringClass()));
         $foreign_class = $reflection_class->newInstance($foreign_class_name);
     }
     return $foreign_class;
 }
Ejemplo n.º 9
0
 /**
  * @param $value  string class name taken from the import array
  * @return string class name (built and with added namespace, if needed)
  */
 public static function getClassNameFromValue($value)
 {
     return isset($value) ? Builder::className($value) : null;
 }
Ejemplo n.º 10
0
 /**
  * Gets URI parameter as an object
  *
  * Object is of class $parameter name, and is read from current data link using the parameter
  * value as identifier.
  *
  * @param $parameter_name string
  * @return object
  */
 public function getObject($parameter_name)
 {
     if (isset($this->objects[$parameter_name])) {
         // parameter is in cache
         $object = $this->objects[$parameter_name];
     } elseif (is_numeric($this->getRawParameter($parameter_name))) {
         if (isset($parameter_name[0]) && ctype_upper($parameter_name[0])) {
             $class_name = $parameter_name;
         }
         if (isset($class_name) && @class_exists($class_name)) {
             // object parameter
             $object = $this->getRawParameter($parameter_name) + 0;
             Mapper\Getter::getObject($object, $class_name);
             $this->objects[$parameter_name] = $object;
         } else {
             // free parameter
             $object = $this->getRawParameter($parameter_name);
             $this->objects[$parameter_name] = $object;
         }
     } else {
         // text parameter
         $object = $this->getRawParameter($parameter_name);
         if (is_string($object) && $object && $object[0] === SL) {
             $object = new Uri($object);
         }
         $this->objects[$parameter_name] = $object;
     }
     if (empty($object)) {
         $built_parameter_name = Builder::className($parameter_name);
         if ($built_parameter_name != $parameter_name) {
             return $this->getObject(Builder::className($parameter_name));
         }
     }
     return $object;
 }
Ejemplo n.º 11
0
 /**
  * Search objects from data source
  *
  * It is highly recommended to instantiate the $what object using Search_Object::instantiate() in order to initialize all properties as unset and build a correct search object.
  * If some properties are an not-loaded objects, the search will be done on the object identifier, without joins to the linked object.
  * If some properties are loaded objects : if the object comes from a read, the search will be done on the object identifier, without join. If object is not linked to data-link, the search is done with the linked object as others search criterion.
  *
  * @param $what       object|array source object for filter, or filter array (need class_name) only set properties will be used for search
  * @param $class_name string must be set if $what is a filter array and not an object
  * @param $options    Option[] some options for advanced search
  * @return object[] a collection of read objects
  */
 public function search($what, $class_name = null, $options = [])
 {
     if (!isset($class_name)) {
         $class_name = get_class($what);
     }
     $class_name = Builder::className($class_name);
     $builder = new Select($class_name, null, $what, $this, $options);
     $query = $builder->buildQuery();
     $this->setContext($builder->getJoins()->getClassNames());
     $result_set = $this->connection->query($query);
     if ($options) {
         $this->getRowsCount($result_set, 'SELECT', $options);
     }
     $objects = $this->fetchAll($class_name, $options, $result_set);
     $this->afterReadMultiple($objects, $options);
     return $objects;
 }
Ejemplo n.º 12
0
 /**
  * @param $class_name string
  */
 public function setClass($class_name)
 {
     if ($this->started) {
         $this->stop();
     }
     $this->class = new Reflection_Class(Builder::className($class_name));
     $this->defaults = $this->class->getDefaultProperties();
 }
Ejemplo n.º 13
0
 /**
  * Generate a new Sql_Join instance, with initialization of all it's properties
  *
  * @param $mode           integer
  * @param $master_alias   string
  * @param $master_column  string
  * @param $foreign_table  string
  * @param $foreign_alias  string
  * @param $foreign_column string
  * @param $type           string
  * @param $foreign_class  string
  * @return Join
  */
 public static function newInstance($mode, $master_alias, $master_column, $foreign_alias, $foreign_table, $foreign_column, $type = self::SIMPLE, $foreign_class = null)
 {
     $sql_join = new Join();
     $sql_join->foreign_alias = $foreign_alias;
     $sql_join->foreign_class = isset($foreign_class) ? Framework\Builder::className($foreign_class) : null;
     $sql_join->foreign_column = $foreign_column;
     $sql_join->foreign_table = $foreign_table;
     $sql_join->master_alias = $master_alias;
     $sql_join->master_column = $master_column;
     $sql_join->mode = $mode;
     $sql_join->type = $type;
     return $sql_join;
 }
Ejemplo n.º 14
0
 /**
  * @param $base_class   string The base name for the class, ie 'SAF\Framework\User'
  * @param $feature_name string The name of the feature, ie 'dataList'
  * @param $suffix       string Class suffix, ie 'Controller', 'View'
  * @param $extension    string File extension, ie 'php', 'html'
  * @param $class_form   boolean true to use 'Feature_Class' naming instead of 'featureClass'
  * @return string[] [$class, $method]
  */
 public static function get($base_class, $feature_name, $suffix, $extension, $class_form = true)
 {
     // ie : $feature_class = 'featureName' transformed into 'Feature_Name'
     $feature_class = Names::methodToClass($feature_name);
     // $feature_what is $feature_class or $feature_name depending on $class_name
     $feature_what = $class_form ? $feature_class : $feature_name;
     $_suffix = $suffix ? '_' . $suffix : '';
     $class_name = $base_class;
     $ext = DOT . $extension;
     $method = 'run';
     $application_classes = Application::current()->getClassesTree();
     // $classes : the controller class name and its parents
     // ['Vendor\Application\Module\Class_Name' => '\Module\Class_Name']
     $classes = [];
     do {
         $classes[$class_name] = substr($class_name, strpos($class_name, BS, strpos($class_name, BS) + 1) + 1);
         if (@class_exists($class_name)) {
             $reflection_class = new Reflection_Class(Builder::className($class_name));
             foreach ($reflection_class->getTraits() as $trait) {
                 $classes[$trait->name] = explode(BS, $trait->name, 3)[2];
             }
             foreach ($reflection_class->getListAnnotation('extends')->values() as $extends) {
                 $classes[$extends] = explode(BS, $extends, 3)[2];
             }
         }
         $class_name = @get_parent_class($class_name);
     } while ($class_name);
     // Looking for specific controller for each application
     $application_class = reset($application_classes);
     do {
         $namespace = Namespaces::of($application_class);
         // for the controller class and its parents
         foreach ($classes as $short_class_name) {
             $class_name = $namespace . BS . $short_class_name;
             $path = strtolower(str_replace(BS, SL, $class_name));
             if (isset($GLOBALS['D'])) {
                 echo '- try A1 ' . $path . SL . $feature_what . $_suffix . $ext . BR;
             }
             if (file_exists($path . SL . $feature_what . $_suffix . $ext)) {
                 $class = $class_name . BS . $feature_what . $_suffix;
                 break 2;
             }
             if (isset($GLOBALS['D'])) {
                 echo '- try A2 ' . $path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR;
             }
             if (file_exists($path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) {
                 $class = $class_name . BS . $feature_class . BS . $feature_what . $_suffix;
                 break 2;
             }
             if (isset($GLOBALS['D']) && $suffix) {
                 echo '- try A3 ' . $path . SL . strtolower($feature_class) . SL . $suffix . $ext . BR;
             }
             if ($suffix && file_exists($path . SL . strtolower($feature_class) . SL . $suffix . $ext)) {
                 $class = $class_name . BS . $feature_class . BS . $suffix;
                 break 2;
             }
             if (isset($GLOBALS['D'])) {
                 echo '- try A4 ' . Names::classToPath($class_name) . '_' . $feature_what . $_suffix . $ext . BR;
             }
             if (file_exists(Names::classToPath($class_name) . '_' . $feature_what . $_suffix . $ext)) {
                 $class = $class_name . '_' . $feature_what . $_suffix;
                 break 2;
             }
             if (isset($GLOBALS['D']) && $suffix) {
                 echo '- try A5 ' . $path . SL . $suffix . $ext . BR;
             }
             if ($suffix && file_exists($path . SL . $suffix . $ext) && method_exists($class_name . BS . $suffix, 'run' . ucfirst($feature_name))) {
                 $class = $class_name . BS . $suffix;
                 $method = 'run' . ucfirst($feature_name);
                 break 2;
             }
         }
         // next application is the parent one
         $application_class = next($application_classes);
     } while ($application_class);
     // Looking for default controller for each application
     if (empty($class)) {
         reset($application_classes);
         do {
             // looking for default controller
             $path = strtolower(str_replace(BS, SL, $namespace));
             if (isset($GLOBALS['D']) && $suffix) {
                 echo '- try B1 ' . $path . SL . strtolower($feature_class) . SL . $suffix . $ext . BR;
             }
             if ($suffix && file_exists($path . SL . strtolower($feature_class) . SL . $suffix . $ext)) {
                 $class = $namespace . BS . $feature_class . BS . $suffix;
                 break;
             }
             if (isset($GLOBALS['D'])) {
                 echo '- try B2 ' . $path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR;
             }
             if (file_exists($path . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) {
                 $class = $namespace . BS . $feature_class . BS . $feature_what . $_suffix;
                 break;
             }
             if (isset($GLOBALS['D']) && $suffix) {
                 echo '- try B3 ' . $path . SL . 'widget' . SL . strtolower($feature_class) . SL . $suffix . $ext . BR;
             }
             if ($suffix && file_exists($path . SL . 'widget' . SL . strtolower($feature_class) . SL . $suffix . $ext)) {
                 $class = $namespace . BS . 'Widget' . BS . $feature_class . BS . $suffix;
                 break;
             }
             if (isset($GLOBALS['D'])) {
                 echo '- try B4 ' . $path . SL . 'widget' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR;
             }
             if (file_exists($path . SL . 'widget' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) {
                 $class = $namespace . BS . 'Widget' . BS . $feature_class . BS . $feature_what . $_suffix;
                 break;
             }
             if (isset($GLOBALS['D']) && $suffix) {
                 echo '- try B5 ' . $path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $suffix . $ext . BR;
             }
             if ($suffix && file_exists($path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $suffix . $ext)) {
                 $class = $namespace . BS . 'Webservice' . BS . $feature_class . BS . $suffix;
                 break;
             }
             if (isset($GLOBALS['D'])) {
                 echo '- try B6 ' . $path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext . BR;
             }
             if (file_exists($path . SL . 'webservice' . SL . strtolower($feature_class) . SL . $feature_what . $_suffix . $ext)) {
                 $class = $namespace . BS . 'Webservice' . BS . $feature_class . BS . $feature_what . $_suffix;
                 break;
             }
             // next application is the parent one
         } while (next($application_classes));
         // Looking for direct feature call, without using any controller
         static $last_controller_class = '';
         static $last_controller_method = '';
         if (empty($class) && (strpos($suffix, 'View') === false || $last_controller_class !== $base_class && $last_controller_method !== $feature_name)) {
             if (strpos($suffix, 'Controller') !== false) {
                 $last_controller_class = $base_class;
                 $last_controller_method = $feature_name;
             }
             if (@method_exists($base_class, $feature_name)) {
                 $class = $base_class;
                 $method = $feature_name;
             }
         }
         // Looking for default controller for each application
         if (empty($class) && $suffix) {
             reset($application_classes);
             // $suffix == 'Html_View' => $sub = 'View/Html', $suffix = 'View'
             if (strpos($suffix, '_')) {
                 $elements = explode('_', $suffix);
                 $sub = join(SL, array_reverse($elements));
                 $suffix = end($elements);
             } else {
                 $sub = $suffix;
             }
             do {
                 if (isset($GLOBALS['D'])) {
                     echo '- try C2 ' . $path . SL . strtolower($sub) . '/Default_' . $suffix . $ext . BR;
                 }
                 if (file_exists($path . SL . strtolower($sub) . '/Default_' . $suffix . $ext)) {
                     $class = $namespace . BS . str_replace(SL, BS, $sub) . BS . 'Default_' . $suffix;
                     break;
                 }
             } while (next($application_classes));
         }
     }
     $result = [isset($class) ? $class : null, $method];
     if (isset($GLOBALS['D'])) {
         echo '- FOUND ' . join('::', $result) . BR;
     }
     return $result;
 }