/** * Attempts to dispatch the supplied Route object * * @param \THCFrame\Router\Route $route * @throws Exception\Module * @throws Exception\Controller * @throws Exception\Action */ public function dispatch(\THCFrame\Router\Route $route) { $module = trim($route->getModule()); $class = trim($route->getController()); $action = trim($route->getAction()); $parameters = $route->getMapArguments(); if ('' === $module) { throw new Exception\Module('Module Name not specified'); } elseif ('' === $class) { throw new Exception\Controller('Class Name not specified'); } elseif ('' === $action) { throw new Exception\Action('Method Name not specified'); } $status = $this->loadConfigFromDb($module . 'status'); if ($status !== null && $status != 1) { throw new Exception\Offline('Application is offline'); } $module = str_replace('\\', '', $module); preg_match('/^[a-zA-Z0-9_]+$/', $module, $matches); if (count($matches) !== 1) { throw new Exception\Module(sprintf('Disallowed characters in module name %s', $module)); } $class = str_replace('\\', '', $class); preg_match('/^[a-zA-Z0-9_]+$/', $class, $matches); if (count($matches) !== 1) { throw new Exception\Controller(sprintf('Disallowed characters in class name %s', $class)); } $file_name = strtolower("./modules/{$module}/controller/{$class}.php"); $class = ucfirst($module) . '_Controller_' . ucfirst($class); if (FALSE === file_exists($file_name)) { throw new Exception\Controller(sprintf('Class file %s not found', $file_name)); } else { require_once $file_name; } $this->_activeModule = $module; Event::fire('framework.dispatcher.controller.before', array($class, $parameters)); try { $instance = new $class(array('parameters' => $parameters)); Registry::set('controller', $instance); } catch (\Exception $e) { throw new Exception\Controller(sprintf('Controller %s error: %s', $class, $e->getMessage())); } Event::fire('framework.dispatcher.controller.after', array($class, $parameters)); if (!method_exists($instance, $action)) { $instance->willRenderLayoutView = false; $instance->willRenderActionView = false; throw new Exception\Action(sprintf('Action %s not found', $action)); } $inspector = new Inspector($instance); $methodMeta = $inspector->getMethodMeta($action); if (!empty($methodMeta['@protected']) || !empty($methodMeta['@private'])) { throw new Exception\Action(sprintf('Action %s not found', $action)); } $hooks = function ($meta, $type) use($inspector, $instance) { if (isset($meta[$type])) { $run = array(); foreach ($meta[$type] as $method) { $hookMeta = $inspector->getMethodMeta($method); if (in_array($method, $run) && !empty($hookMeta['@once'])) { continue; } $instance->{$method}(); $run[] = $method; } } }; Event::fire('framework.dispatcher.beforehooks.before', array($action, $parameters)); $hooks($methodMeta, '@before'); Event::fire('framework.dispatcher.beforehooks.after', array($action, $parameters)); Event::fire('framework.dispatcher.action.before', array($action, $parameters)); call_user_func_array(array($instance, $action), is_array($parameters) ? $parameters : array()); Event::fire('framework.dispatcher.action.after', array($action, $parameters)); Event::fire('framework.dispatcher.afterhooks.before', array($action, $parameters)); $hooks($methodMeta, '@after'); Event::fire('framework.dispatcher.afterhooks.after', array($action, $parameters)); // unset controller Registry::erase('controller'); }
/** * There are four basic parts to our __call() method: * checking to see that the inspector is set, * handling the getProperty() methods, handling the setProperty() methods and * handling the unsProperty() methods * * @param string $name * @param string $arguments * @return null|\THCFrame\Core\Base * @throws Exception */ public function __call($name, $arguments) { if (empty($this->_inspector)) { throw new Exception('Call parent::__construct!'); } $getMatches = StringMethods::match($name, '#^get([a-zA-Z0-9_]+)$#'); if (count($getMatches) > 0) { $normalized = lcfirst($getMatches[0]); $property = "_{$normalized}"; if (property_exists($this, $property)) { $meta = $this->_inspector->getPropertyMeta($property); if (empty($meta['@readwrite']) && empty($meta['@read'])) { throw $this->_getWriteonlyException($normalized); } unset($meta); if (isset($this->{$property})) { return $this->{$property}; } else { return null; } } elseif (array_key_exists($normalized, $this->_dataStore)) { return $this->_dataStore[$normalized]; } else { return null; } } unset($getMatches); $setMatches = StringMethods::match($name, '#^set([a-zA-Z0-9_]+)$#'); if (count($setMatches) > 0) { $normalized = lcfirst($setMatches[0]); $property = "_{$normalized}"; if (property_exists($this, $property)) { $meta = $this->_inspector->getPropertyMeta($property); if (empty($meta['@readwrite']) && empty($meta['@write'])) { throw $this->_getReadonlyException($normalized); } unset($meta); $this->{$property} = $arguments[0]; return $this; } else { //if variable is not class property its stored into _dataStore array $this->_dataStore[$normalized] = $arguments[0]; return $this; } } unset($setMatches); $unsetMatches = StringMethods::match($name, '#^uns([a-zA-Z0-9_]+)$#'); if (count($unsetMatches) > 0) { $normalized = lcfirst($setMatches[0]); $property = "_{$normalized}"; if (property_exists($this, $property)) { $meta = $this->_inspector->getPropertyMeta($property); if (empty($meta['@readwrite']) && empty($meta['@write'])) { throw $this->_getReadonlyException($normalized); } unset($meta); unset($this->{$property}); return $this; } else { unset($this->_dataStore[$normalized]); return $this; } } unset($unsetMatches); throw $this->_getImplementationException($name); }
/** * Method creates an Inspector instance and a utility function ($first) to return the * first item in a metadata array. Next, it loops through all the properties in the model, * and sifts out all that have an @column flag. Any other properties are ignored at this point. * The column’s @type flag is checked to make sure it is valid, raising a * Model\Exception\Type in the event that it is not. If the column’s type is valid, * it is added to the $_columns property. Every valid $primary column leads to the * incrementing of the $primaries variable, which is checked at the end * of the method to make sure that exactly one primary column has been defined. * In essence, this method takes the User model definition and returns an associative array of column data * * @return array * @throws Exception\Type * @throws Exception\Primary */ public function getColumns() { if (empty($this->_columns)) { $primaries = 0; $columns = array(); $class = get_class($this); $types = $this->_types; $inspector = new Inspector($this); $properties = $inspector->getClassProperties(); $first = function ($array, $key) { if (!empty($array[$key]) && count($array[$key]) == 1) { return $array[$key][0]; } return null; }; foreach ($properties as $property) { $propertyMeta = $inspector->getPropertyMeta($property); if (!empty($propertyMeta['@column'])) { $name = preg_replace('#^_#', '', $property); $primary = !empty($propertyMeta['@primary']); $type = $first($propertyMeta, '@type'); $length = $first($propertyMeta, '@length'); $index = !empty($propertyMeta['@index']); $unique = !empty($propertyMeta['@unique']); $readwrite = !empty($propertyMeta['@readwrite']); $read = !empty($propertyMeta['@read']) || $readwrite; $write = !empty($propertyMeta['@write']) || $readwrite; $validate = !empty($propertyMeta['@validate']) ? $propertyMeta['@validate'] : false; $label = $first($propertyMeta, '@label'); if (!in_array($type, $types)) { throw new Exception\Type(sprintf('%s is not a valid type', $type)); } if ($primary) { $primaries++; } $columns[$name] = array('raw' => $property, 'name' => $name, 'primary' => $primary, 'type' => $type, 'length' => $length, 'index' => $index, 'unique' => $unique, 'read' => $read, 'write' => $write, 'validate' => $validate, 'label' => $label); } } if ($primaries !== 1) { throw new Exception\Primary(sprintf('%s must have exactly one @primary column', $primary)); } $this->_columns = $columns; } return $this->_columns; }