Example #1
0
 /**
  * Receives events generated in the models and dispatches them to a events-manager if available
  * Notify the behaviors that are listening in the model
  *
  * @param string $eventName
  * @param \Phalcon\Mvc\CollectionInterface $model
  * @return mixed
  * @throws Exception
  */
 public function notifyEvent($eventName, $model)
 {
     if (is_string($eventName) === false || is_object($model) === false || $model instanceof CollectionInterface === false) {
         throw new Exception('Invalid parameter type.');
     }
     //Dispatch events to the global events manager
     if (is_object($this->_eventsManager) === true) {
         $status = $this->_eventsManager->fire('collection:' . $eventName, $model);
         if ($status === false) {
             return false;
         }
     }
     //A model can have a specific events manager
     if (is_array($this->_customEventsManager) === true) {
         $entityName = strtolower(get_class($model));
         if (isset($this->_customEventsManager[$entityName]) === true) {
             $status = $this->_customEventsManager[$entityName]->fire('collection:' . $eventName, $model);
         }
     }
     return $status;
 }
Example #2
0
 /**
  * Dispatch a event to the listeners and behaviors
  * This method expects that the endpoint listeners/behaviors returns true
  * meaning that a least one is implemented
  *
  * @param \Phalcon\Mvc\ModelInterface $model
  * @param string $eventName
  * @param array $data
  * @return mixed
  * @throws Exception
  */
 public function missingMethod($model, $eventName, $data)
 {
     if (is_object($model) === false || $model instanceof ModelInterface === false || is_string($eventName) === false || is_array($data) === false) {
         throw new Exception('Invalid parameter type.');
     }
     if (is_array($this->_behaviors) === true) {
         $entityName = strtolower(get_class($model));
         if (isset($this->_behaviors[$entityName]) === true) {
             //Notify all the events on the behavior
             foreach ($this->_behaviors[$entityName] as $behavior) {
                 $result = $behavior->missingMethod($model, $eventName, $data);
                 if (is_null($result) === false) {
                     return $result;
                 }
             }
         }
     }
     //Dispatch events to the global events manager
     if (is_object($this->_eventsManager) === true) {
         return $this->_eventsManager->fire('model:' . $eventName, $model, $data);
     }
     return null;
 }
Example #3
0
 /**
  * Handle the command-line arguments.
  *
  *
  * <code>
  *  $arguments = array(
  *      'task' => 'taskname',
  *      'action' => 'action',
  *      'params' => array('parameter1', 'parameter2')
  *  );
  *  $console->handle($arguments);
  * </code>
  *
  * @param array $arguments
  * @return mixed
  * @throws Exception
  */
 public function handle($arguments = null)
 {
     /* Type check */
     if (is_null($arguments) === true) {
         $arguments = array();
     } elseif (is_array($arguments) === false) {
         throw new Exception('Invalid parameter type.');
     }
     if (is_object($this->_dependencyInjector) === false) {
         throw new Exception('A dependency injection object is required to access internal services');
     }
     $router = $this->_dependencyInjector->getShared('router');
     $router->handle($arguments);
     $moduleName = $router->getModuleName();
     if (isset($moduleName) === true) {
         //Event: console:beforeStartModule
         if (is_object($this->_eventsManager) === true) {
             if ($this->_eventsManager->fire('console:beforeStartModule', $this, $moduleName) === false) {
                 return false;
             }
         }
         //Validate module structure
         if (is_array($this->_modules) === false || isset($this->_modules[$moduleName]) === false) {
             throw new Exception('Module \'' . $moduleName . '\' isn\'t registered in the console container');
         }
         if (is_array($this->_modules[$moduleName]) === false) {
             throw new Exception('Invalid module definition path');
         }
         //Require ['path']
         if (isset($this->_modules[$moduleName]['path']) === true) {
             if (file_exists($this->_modules[$moduleName]['path']) === true) {
                 require $this->_modules[$moduleName]['path'];
             } else {
                 throw new Exception('Module definition path \'' . $this->_modules[$moduleName]['path'] . '" doesn\'t exist');
             }
         }
         //Get class name
         if (isset($this->_modules[$moduleName]['className']) === true) {
             $className = $this->_modules[$moduleName]['className'];
         } else {
             $className = 'Module';
         }
         //Prepare $moduleObject
         $moduleObject = $this->_dependencyInjector->get($className);
         $moduleObject->registerAutoloaders();
         $moduleObject->registerServices($this->_dependencyInjector);
         //Event: console:afterStartModule
         if (is_object($this->_eventsManager) === true) {
             $this->_moduleObject = $moduleObject;
             if ($this->_eventsManager->fire('console:afterStartModule', $this, $moduleName) === false) {
                 return false;
             }
         }
     }
     //Get route
     $taskName = $router->getTaskName();
     $actionName = $router->getActionName();
     $params = $router->getParams();
     //Get dispatcher
     $dispatcher = $this->_dependencyInjector->getShared('dispatcher');
     if (is_object($dispatcher) === false || $dispatcher instanceof DispatcherInterface === false) {
         throw new Exception('Dispatcher service is not available.');
     }
     //Set route
     $dispatcher->setTaskName($taskName);
     $dispatcher->setActionName($actionName);
     $dispatcher->setParams($params);
     //Event: console:beforeHandleTask
     if (is_object($this->_eventsManager) === true) {
         if ($this->_eventsManager->fire('console:beforeHandleTask', $this, $dispatcher) === false) {
             return false;
         }
     }
     //Dispatch
     $task = $dispatcher->dispatch();
     if (is_object($this->_eventsManager) === true) {
         $this->_eventsManager->fire('console:afterHandleTask', $this, $task);
     }
     return $task;
 }
Example #4
0
 /**
  * Dispatches a handle action taking into account the routing parameters
  *
  * @return object|boolean
  */
 public function dispatch()
 {
     if (is_object($this->_dependencyInjector) === false) {
         $this->_throwDispatchException('A dependency injection container is required to access related dispatching services', self::EXCEPTION_NO_DI);
         return false;
     }
     if (is_object($this->_eventsManager) === true) {
         if ($this->_eventsManager->fire('dispatch:beforeDispatchLoop', $this) === false) {
             return false;
         }
     }
     $numberDispatches = 0;
     $this->_finished = false;
     $handler = null;
     while (true) {
         //Loop until finished is false
         if ($this->_finished === true) {
             break;
         }
         ++$numberDispatches;
         //Throw an exception after 256 consecutive forwards
         if ($numberDispatches >= 256) {
             $this->_throwDispatchException('Dispatcher has detected a cyclic routing causing stability problems', self::EXCEPTION_CYCLIC_ROUTING);
             break;
         }
         $this->_finished = true;
         //If the current namespace is null we use the set in $this->_defaultNamespace
         if (is_null($this->_namespaceName) === true) {
             $this->_namespaceName = $this->_defaultNamespace;
         }
         //If the handler is null we use the set in $this->_defaultHandler
         if (is_null($this->_handlerName) === true) {
             $this->_handlerName = $this->_defaultHandler;
         }
         //If the action is null we use the set in $this->_defaultAction
         if (is_null($this->_actionName) === true) {
             $this->_actionName = $this->_defaultAction;
         }
         //Calling beforeDispatch
         if (is_object($this->_eventsManager) === true) {
             if ($this->_eventsManager->fire('dispatch:beforeDispatch', $this) === false) {
                 continue;
             }
             //Check if the user made a forward in the listener
             if ($this->_finished === false) {
                 continue;
             }
         }
         //We don't camelize the classes if they are in namespaces
         $p = strpos($this->_handlerName, '\\');
         if ($p === false) {
             $camelizedClass = Text::camelize($this->_handlerName);
         } elseif ($p === 0) {
             //@note this only handles one leading slash
             $camelizedClass = substr($this->_handlerName, strlen($this->_handlerName) + 1);
         } else {
             $camelizedClass = $this->_handlerName;
         }
         //Create the complete controller class name prepending the namespace
         if (is_null($this->_namespaceName) === false) {
             if (strrpos($this->_namespaceName, '\\') === strlen($this->_namespaceName) - 1) {
                 $handlerClass = $this->_namespaceName . $camelizedClass . $this->_handlerSuffix;
             } else {
                 $handlerClass = $this->_namespaceName . '\\' . $camelizedClass . $this->_handlerSuffix;
             }
         } else {
             $handlerClass = $camelizedClass . $this->_handlerSuffix;
         }
         //Handlers are retrieved as shared instances from the Service Container
         if ($this->_dependencyInjector->has($handlerClass) === false) {
             //Check using autoloading
             if (class_exists($handlerClass) === false) {
                 if ($this->_throwDispatchException($handlerClass . ' handler class cannot be loaded', self::EXCEPTION_HANDLER_NOT_FOUND) === false) {
                     if ($this->_finished === false) {
                         continue;
                     }
                 }
                 break;
             }
         }
         //Handlers must be only objects
         $handler = $this->_dependencyInjector->getShared($handlerClass);
         if (is_object($handler) === false) {
             if ($this->_throwDispatchException('Invalid handler returned from the services container', self::EXCEPTION_INVALID_HANDLER) === false) {
                 if ($this->_finished === false) {
                     continue;
                 }
             }
             break;
         }
         //If the object was recently created in the DI we initialize it
         $wasFresh = $this->_dependencyInjector->wasFreshInstance();
         $this->_activeHandler = $handler;
         //Check if the method exists in the handler
         $actionMethod = $this->_actionName . $this->_actionSuffix;
         if (method_exists($handler, $actionMethod) === false) {
             //Call beforeNotFoundAction
             if (is_object($this->_eventsManager) === true) {
                 if ($this->_eventsManager->fire('dispatch:beforeNotFoundAction', $this) === false) {
                     continue;
                 }
                 if ($this->_finished === false) {
                     continue;
                 }
             }
             if ($this->_throwDispatchException('Action \'' . $this->_actionName . '\' was not found on handler \'' . $this->_handlerName . '\'', self::EXCEPTION_ACTION_NOT_FOUND) === false) {
                 if ($this->_finished === false) {
                     continue;
                 }
             }
             break;
         }
         //Calling beforeExecuteRoute
         if (is_object($this->_eventsManager) === true) {
             if ($this->_eventsManager->fire('dispatch:beforeExecuteRoute', $this) === false) {
                 continue;
             }
             //Check if the user made a forward in the listener
             if ($this->_finished === false) {
                 continue;
             }
         }
         //Calling beforeExecuteRoute as callback and event
         if (method_exists($handler, 'beforeExecuteRoute') === true) {
             if ($handler->beforeExecuteRoute($this) === false) {
                 continue;
             }
             //Check if the user made a forward in the listener
             if ($this->_finished === false) {
                 continue;
             }
         }
         //Check if params is an array
         if (is_array($this->_params) === false) {
             if ($this->_throwDispatchException('Action parameters must be an Array', self::EXCEPTION_INVALID_PARAMS) === false) {
                 if ($this->_finished === false) {
                     continue;
                 }
             }
             break;
         }
         //Call the 'initialize' method just once per request
         if ($wasFresh === true) {
             if (method_exists($handler, 'initialize') === true) {
                 $handler->initialize();
             }
         }
         //Call the method with/without exceptions if an events manager is present
         if (is_object($this->_eventsManager) === true) {
             try {
                 //Call the method allowing exceptions
                 $m = new ReflectionMethod($handler, $actionMethod);
                 $value = $m->invokeArgs($handler, $this->_params);
             } catch (\Exception $exception) {
                 //Copy the exception to rethrow it later if needed
                 //Try to handle the exception
                 if ($this->_handleException($exception) === false) {
                     if ($this->_finished === false) {
                         continue;
                     }
                 } else {
                     //Exception wasn't handled, rethrow it
                     throw new Exception($exception);
                 }
             }
             //Update the latest value produced by the latest handler
             $this->_returnedValue = $value;
         } else {
             //Call the method handling exceptions as normal
             $this->_returnedValue = call_user_func_array(array($handler, $actionMethod), $this->_params);
         }
         $this->_lastHandler = $handler;
         //Calling afterExecuteRoute
         if (is_object($this->_eventsManager) === true) {
             if ($this->_eventsManager->fire('dispatch:afterExecuteRoute', $this) === false) {
                 continue;
             }
             if ($this->_finished === false) {
                 continue;
             }
             //Calling afetDispatch
             $this->_eventsManager->fire('dispatch:afterDispatch', $this);
         }
         //Calling afterExecuteRoute as callback and event
         if (method_exists($handler, 'afterExecuteRoute') === true) {
             if ($handler->afterExecuteRoute($this, $this->_returnedValue) === false) {
                 continue;
             }
             if ($this->_finished === false) {
                 continue;
             }
         }
     }
     //Call afterDispatchLoop
     if (is_object($this->_eventsManager) === true) {
         $this->_eventsManager->fire('dispatch:afterDispatchLoop', $this);
     }
     return $handler;
 }