Exemplo n.º 1
0
 /**
  * Invoke a prototyped resource from a caller context
  *
  * @param Next\Components\Object $caller
  *   Caller Object
  *
  * @param string $method
  *   Callable resource name
  *
  * @param array $args
  *   Calling Arguments
  *
  * @return Next\Components\Object
  *   Caller Object updated
  *
  * @throws Next\Components\Debug\Exception
  *   Called resource is not known as a prototype nor as a extended method
  */
 public function call(Object $caller, $method, array $args = array())
 {
     if (isset(self::$prototypes[$method])) {
         // Merging always optional arguments with called arguments
         if (count($args) > 0) {
             ArrayUtils::insert(self::$prototypes[$method][1], $args);
         } else {
             // Nothing to Merge? OK!
             $args =& self::$prototypes[$method][1];
         }
         $result = call_user_func_array(self::$prototypes[$method][0], $args);
         /**
          * @internal
          *
          * If operation results in an Object, let's return it
          *
          * This ensures operations of one type can return a different type
          */
         if ($result instanceof Object) {
             return $result;
         }
         // Otherwise let's update caller Object
         return $caller->set($result);
     }
     throw \Next\Components\Debug\Exception::wrongUse('Method <strong>%s</strong> could not be matched against any
         methods in extended Context or prototyped functions', array($method));
 }
Exemplo n.º 2
0
 /**
  * Add ORDER BY Clause(s)
  *
  * @param string|array $field
  *
  *   <p>As string, field to lead the ordenation.</p>
  *
  *   <p>
  *       As associative array, keys are the fields and values
  *       ordenation types
  *   </p>
  *
  * @param string|optional $type
  *
  *   <p>Type of ordenation: ASC or DESC.</p>
  *
  *   <p>
  *       If <strong>$field</strong> is an array, this value is not
  *       immediately used
  *   </p>
  *
  * @return Next\DB\Query\Builder
  *   Builder Instance (Fluent Interface)
  *
  * @throws Next\DB\Query\QueryException
  *   Ordenation field is empty or was considered an empty string
  */
 public function order($field, $type = self::SQL_ORDER_ASC)
 {
     // Do we have multiple ORDER BY clause?
     if (is_array($field)) {
         if (is_array($type)) {
             // Both arguments are arrays, let's equalize their lengths...
             ArrayUtils::equalize($field, $type);
             // ... and combine to make recursion easily
             $field = array_combine($field, $type);
         }
         /**
          * @internal
          * Only first argument is array, so we expect it to be
          * an associative pair/value as field to order => ordenation type
          */
         foreach ($field as $f => $t) {
             $this->order($f, $t);
         }
     } else {
         // Ensuring we have a Field to lead the ordenation
         $field = trim((string) $field);
         if (empty($field)) {
             throw QueryException::logic('Field to order results must be set as non-empty string');
         }
         // Ensuring we have a ordening direction (even optional for most RDBMS)
         $type = trim((string) $type);
         if (empty($type)) {
             $type = self::SQL_ORDER_ASC;
         }
         /**
          * @internal
          * ORDER BY Clause cannot be "prepared", at least not as a question
          * mark placeholder, because for some reason PDO::prepare() will
          * try to wrap the values (field and ordenation type) into quotes,
          * invalidating this specific part of SQL Statement
          */
         self::$parts[self::SQL_ORDER_BY][$field] = $type;
     }
     return $this;
 }
Exemplo n.º 3
0
 /**
  * Compare given value in a [List|of|Possible|Values]
  *
  * @param string $value
  *   Value to compare
  *
  * @param string $list
  *   List to compare given value
  *
  * @return string|NULL
  *
  *   - If given parameter lacks the Separator Token OR
  *     if it IS present in a List of Possible Values, it will be returned "as is"
  *
  *   - Otherwise we'll try to find the proper Default Value.
  *     If we succeed, this value will be returned. Otherwise NULL will
  */
 private function compareWithList($value, $list)
 {
     // Mal-formed List?
     if (strpos($list, self::SEPARATOR_TOKEN) === FALSE) {
         // Let's use what we received
         return $value;
     } else {
         // Parameter is in the List?
         // Removing Default Value Definition of given list in order to split correctly
         $l = preg_replace(sprintf('/%s/', self::DEFAULT_VALUE_REGEXP), '', $list);
         if (ArrayUtils::in($value, explode(self::SEPARATOR_TOKEN, $l))) {
             return $value;
         }
         // No? Let's try to find the Default Value
         return $this->getDefaultValue($list);
     }
 }
Exemplo n.º 4
0
 /**
  * Parse one or more Routes, recursively
  *
  * @param string|array $routes
  *   Route(s) to be parsed
  *
  * @param string $controller
  *   Controller to whom belongs the Route(s)
  *
  * @param string $method
  *   Method to whom belongs the Route(s)
  *
  * @throws Next\Tools\RoutesGenerator\RoutesGeneratorException
  *   Route has less than 2 Components (a Request Method and a Route)
  *
  * @throws Next\Tools\RoutesGenerator\RoutesGeneratorException
  *   Routes defined as single slash (usually for homepages) DO have
  *   arguments (hierarchy concept)
  *
  * @throws Next\Tools\RoutesGenerator\RoutesGeneratorException
  *   There is another Route with exactly the same definition, including
  *   the Request Method
  */
 private function parseRoutes($routes, $controller, $method, $basepath)
 {
     if (is_array($routes)) {
         foreach ($routes as $route) {
             $this->parseRoutes($route, $controller, $method, $basepath);
         }
     } else {
         // Listing Route Components
         $components = explode(',', $routes);
         if (count($components) < 2) {
             throw RoutesGeneratorException::invalidRouteStructure(array($routes, basename($controller), $method));
         }
         // Shifting Request Method
         $requestMethod = trim(array_shift($components));
         // ... and URI Route
         $URI = trim(array_shift($components));
         // If we still have some components, all them will be treated as Route Params
         $params = array();
         if (count($components) > 0) {
             $params = array_map('trim', $components);
         }
         // Parsing, fixing and complementing them
         /**
          * @internal
          * If defined URI is NOT a single slash, no trailing slash for it
          * But add a RegExp Border instead
          */
         if ($URI != '/') {
             // Prepending Routes Basepath if present
             if (empty($basepath)) {
                 $URI = sprintf('%s\\b', trim($URI, '/'));
             } else {
                 $URI = sprintf('%s/%s\\b', trim($basepath, '/'), trim($URI, '/'));
             }
             /**
              * @internal
              * If we have a well designed structure, let's add RegExp Delim Captures Token too
              *
              * Routes pointing to a single slash do not have this token due hierarchical logic
              * These kind of Routes cannot even have any params, except the one reserved for Localization
              */
             $URI .= self::DELIM_CAPTURE_TOKEN;
         } else {
             // Let's ensure single slash Routes have no params
             if (!empty($params)) {
                 throw RoutesGeneratorException::malformedRoute(array($URI, basename($controller), $method));
             }
         }
         // Adding an Always Optional Parameter for Localization
         $params[] = self::LOCALE_PARAM;
         // Let's parse Required and Optional Params
         $required = $this->parseParams($params, self::REQUIRED_PARAMS_TOKEN);
         $optional = $this->parseParams($params, self::OPTIONAL_PARAMS_TOKEN);
         // Searching for Duplicates
         $offset = ArrayUtils::search($this->results, $URI, 'route');
         // We found one...
         if ($offset != -1) {
             // ... let's compare with the Request Method
             if ($this->results[$offset]['requestMethod'] == $requestMethod) {
                 // Yeah! We have a Duplicate
                 throw RoutesGeneratorException::duplicatedRoute(array($requestMethod, $URI, basename($controller), $method));
             }
         }
         // Preparing Parsed Route to be recorded
         $this->results[] = array('requestMethod' => $requestMethod, 'route' => $URI, 'params' => array('required' => $required, 'optional' => $optional), 'class' => $controller, 'method' => $method);
     }
 }
Exemplo n.º 5
0
 /**
  * Invoke an extended resource from a caller context
  *
  * @param Next\Components\Object $caller
  *   Caller Object
  *
  * @param string $method
  *   Callable resource name
  *
  * @param array $args
  *   Calling Arguments
  *
  * @return mixed|boolean
  *   Return what extended method returns.
  *
  *   If invoking process fail, false will returned.
  *
  * @throws Next\Components\Debug\Exception
  *   Called resource is not known as an extended method
  */
 public function call(Object $caller, $method, array $args = array())
 {
     $caller = $caller->getClass()->getName();
     if (array_key_exists($caller, $this->callables)) {
         $offset = ArrayUtils::search($this->callables[$caller], $method);
         if ($offset != -1) {
             try {
                 $reflector = new \ReflectionMethod($this->callables[$caller][$offset][0], $method);
                 return $reflector->invokeArgs($this->callables[$caller][$offset][0], $args);
             } catch (\ReflectionException $e) {
                 return FALSE;
             }
         }
     }
     // Unknown Method
     throw \Next\Components\Debug\Exception::wrongUse('Method <strong>%s</strong> could not be matched against any
         methods in extended Context', array($method));
 }
Exemplo n.º 6
0
 /**
  * Get Context Options
  *
  * @param string|optional $option
  *   Desired Context Option
  *
  * @param string|optional $wrapper
  *   Optional Context Option Wrapper
  *
  * @return array|boolean
  *
  *   If <strong>$option</strong> is NOT null and we can't find a match
  *   option FALSE is returned. Otherwise the desired option value
  *   will.
  *
  *   If <strong>$option</strong> argument IS null, all the options defined will be
  *   returned
  *
  *   <strong>$wrapper</strong> argument, if set, can restrict the search and thus avoid a
  *   value to be found
  */
 public function getOptions($option = NULL, $wrapper = NULL)
 {
     if (!is_null($option)) {
         // Looking for the array key where the option COULD be
         $key = ArrayUtils::search($this->options, $option, $wrapper);
         // If it exists, let's return it
         if ($key != -1 && isset($this->options[$key][$option])) {
             return $this->options[$key][$option];
         }
         return FALSE;
     }
     return $this->options;
 }
Exemplo n.º 7
0
 /**
  * Build the Class Map
  *
  * @param string $format
  *   Output Format from Available Formats
  *
  * @param mixed|optional $options
  *   List of Options to affect Database Drivers. Acceptable values are:
  *
  *   <p>
  *
  *       <ul>
  *
  *           <li>Associative and multidimensional array</li>
  *
  *           <li>
  *
  *               An {@link http://php.net/manual/en/reserved.classes.php stdClass Object}
  *
  *           </li>
  *
  *           <li>A well formed Next\Components\Parameter Object</li>
  *
  *       </ul>
  *
  *   </p>
  *
  *   <p>There are no Common Options defined so far.</p>
  *
  *   <p>
  *       All the arguments taken in consideration are defined in
  *       and by factored classes
  *   </p>
  *
  * @see Next\Components\Parameter
  *
  * @return mixed|void
  *   If chosen format allow the result to be returned, it will
  *   accordingly to the its rules
  *
  *   Otherwise, nothing is returned
  *
  * @throws Next\Tools\ClassMapper\ClassMapperException
  *   Invalid or unsupported Mapping Format
  */
 public function build($format, $options = NULL)
 {
     if (!in_array((string) $format, $this->available)) {
         throw ClassMapperException::unknown();
     }
     // Building Definitions
     $map = new \stdClass();
     $iterator =& $this;
     iterator_apply($iterator, function () use($iterator, $map) {
         $file = $iterator->current();
         $namespace = '';
         if (!empty($file->namespace)) {
             $namespace = sprintf('%s\\', $file->namespace);
         }
         $classname = $namespace . $file->classname;
         $map->{$classname} = $file->getRealPath();
         return TRUE;
     });
     // Building Output Format Classname
     $class = sprintf('Next\\Tools\\ClassMapper\\%s', (string) $format);
     // Instantiating Object
     $instance = new $class($options);
     // Building!
     return $instance->build(ArrayUtils::map($map));
 }