示例#1
0
 /**
  * Creates an instance of the appropriate action class
  * then invokes the "execute" method on the instance. An optional
  * framework parameter may be delegated to the action. If
  * the Action implements a method matching the given task, it
  * will be invoked rather than the "execute" method.
  *
  * The return value from the Action will be passed to a
  * corresponding Page instance (created in the same manner) via
  * its "render" method. The given task may override the target
  * method as described above.
  *
  * If the Dispatcher instance is visible in global scope, the Action
  * implementation may dynamically override the task method for the
  * subsequent Page invocation as follows:
  * <pre>
  *     global $dispatcher;
  *     $dispatcher->setTask('pageTask');
  * </pre>
  *
  * @param String $scope	 A key for finding the action/page prefix
  * @param String $task An optional target method to invoke
  */
 public function dispatch($scope, $task = null)
 {
     $timer = Horde_Timer::singleton();
     $timer->push();
     // overall timer for action+page
     $this->setTask($task);
     $this->setRedirect(null);
     $action = $this->getAction($scope);
     if (!is_subclass_of($action, 'BaseAction')) {
         trigger_error("Invalid Action class: get_class({$action})", E_USER_ERROR);
         return;
     }
     $bean = null;
     $method = $this->getTask();
     $timer->push();
     // timer for action
     if (!empty($method) && in_array($method, get_class_methods($action))) {
         $bean = $action->{$method}($this->param);
     } else {
         $bean = $action->execute($this->param);
     }
     $this->timers[$scope . ':action'] = $timer->pop();
     if ($this->getRedirect() == null || $scope == $this->getRedirect() && $task == $this->getTask()) {
         $page = $this->getPage($scope);
         if (!is_subclass_of($page, 'BasePage')) {
             trigger_error("Invalid Page class: get_class({$action})", E_USER_ERROR);
             return;
         }
         $method = $this->getTask();
         $timer->push();
         // timer for page
         if (!empty($method) && in_array($method, get_class_methods($page))) {
             $page->{$method}($bean);
         } else {
             $page->render($bean);
         }
         $this->timers[$scope . ':page'] = $timer->pop();
     } else {
         $this->dispatch($this->getRedirect(), $this->getTask());
     }
     $this->timers[$scope . ':overall'] = $timer->pop();
     Horde::logMessage("Dispatcher timing (ms) for {$scope} [{$this->task}]: " . print_r($this->timers, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
 }
示例#2
0
 /**
  * Returns a list of beans that matched the criteria 
  * given in the arguments
  *
  * @param db A database connection
  * @param namedBean A template bean identifiying the query table/columns
  * @param listBean Query parameters and results
  * @param where optional where clause element(s)
  * @param values optional values for prepared statement elements
  * @return boolean true if the query was successful, else false
  */
 public function select(&$db, $namedBean, &$listBean = null, $where = array(), $values = array())
 {
     Horde_Timer::singleton()->push();
     if (empty($listBean)) {
         $listBean = new ListBean();
     }
     $criteria = $listBean->get_criteria();
     $currentPage = $listBean->get_current_page();
     $pageSize = $listBean->get_page_size();
     $orderBy = $listBean->get_order_by();
     $cols = $namedBean->get_bean_name() . '.*';
     // special handling to build timestamps from date columns
     // This is done to preserve naming convention for dates
     // while allowing the application to convert the value to a date OR
     // timestamp as needed.
     foreach ($namedBean as $key => $value) {
         if (strpos(strtolower($key), 'timestamp') > 0) {
             $cols .= ', TO_CHAR(' . str_replace('timestamp', 'date', $key) . ', \'YYYY-MM-DD HH24:MI:SS\') AS ' . $key;
         }
     }
     foreach ($criteria as $property => $val) {
         $opcode = '=';
         $value = $val;
         if (property_exists(get_class($namedBean), $property) && empty($value)) {
             Horde::logMessage("NOTE: {$property} has empty value in _criteriaQuery", __FILE__, __LINE__, PEAR_LOG_WARNING);
         }
         if (property_exists(get_class($namedBean), $property) && !empty($value)) {
             if (is_object($value) && get_class($value) == 'Criterion') {
                 $value = $val->get_value();
                 $opcode = $val->get_operator();
             }
             if (!is_numeric($value) && ($value == 'null' || $value == 'not null')) {
                 $where[] = $property . ' is ' . $value;
             } else {
                 if (is_array($value)) {
                     $tokens = $delim = '';
                     foreach ($value as $var) {
                         $tokens .= $delim . '?';
                         $delim = ',';
                         $values[] = $var;
                     }
                     if (empty($tokens)) {
                         $where[] = '1=0';
                     } else {
                         if ($opcode == 'between' && count($value) == 2) {
                             $where[] = "{$property} between ? and ?";
                         } else {
                             $where[] = $property . ' in (' . $tokens . ')';
                         }
                     }
                 } else {
                     if (strpos(strtolower($property), 'timestamp') > 0) {
                         $where[] = $property . ' ' . $opcode . ' TO_DATE(?, \'YYYY-MM-DD HH24:MI:SS\')';
                         $values[] = date('Y-m-d H:i:s', strtotime($value));
                     } else {
                         if (strpos(strtolower($property), 'date') > 0) {
                             $where[] = 'trunc(' . $property . ') ' . $opcode . ' TO_DATE(?, \'YYYY-MM-DD\')';
                             $values[] = date('Y-m-d', strtotime($value));
                         } else {
                             if (is_string($value) && !is_numeric($value) && $opcode == '=') {
                                 $where[] = $property . ' like ?';
                                 $values[] = '%' . trim($value) . '%';
                             } else {
                                 $where[] = $property . ' ' . $opcode . ' ?';
                                 $values[] = $value;
                             }
                         }
                     }
                 }
             }
         }
     }
     $sql = 'SELECT ' . $cols . ' FROM ' . $namedBean->get_bean_name() . (count($where) ? ' WHERE ' . join(' AND ', $where) : '');
     $record_count = $listBean->get_record_count();
     if ($record_count == 0) {
         $csql = str_replace($cols, 'COUNT(*) AS count', $sql);
         Horde::logMessage($csql . "\n" . print_r($values, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
         $result = $db->query($csql, $values);
         if (is_a($result, 'PEAR_Error')) {
             $listBean->setError($result);
             QueryUtil::handleError($result, $csql, $values, __LINE__);
             return false;
         }
         $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
         if (is_a($row, 'PEAR_Error')) {
             $listBean->setError($row);
             QueryUtil::handleError($row, $csql, $values, __LINE__);
             return false;
         }
         $record_count = (int) $row['count'];
         $listBean->set_record_count($record_count);
     }
     if ($pageSize < 0) {
         $pageSize = $record_count;
     }
     $firstRow = $currentPage * $pageSize + 1;
     if ($firstRow <= 0) {
         $firstRow = 1;
         $currentPage = 0;
     }
     $lastRow = ($currentPage + 1) * $pageSize;
     if ($lastRow > $record_count) {
         $lastRow = $record_count;
         $currentPage = (int) (($record_count - 1) / $pageSize);
         $firstRow = $currentPage * $pageSize + 1;
     }
     $listBean->set_current_page($currentPage);
     $list = array();
     if ($record_count > 0) {
         global $conf;
         if ($conf['data']['use_ci_sort']) {
             foreach ($orderBy as &$sort) {
                 $parts = explode(' ', $sort);
                 $sort = 'NLS_UPPER(' . $parts[0] . ', \'NLS_SORT = GENERIC_BASELETTER\') ' . (count($parts) > 1 ? $parts[1] : '');
             }
         }
         $psql = 'SELECT * FROM ( SELECT x.*, RowNum AS row_index FROM ( ' . $sql . (count($orderBy) ? ' ORDER BY ' . join(', ', $orderBy) : '') . ' ) x WHERE RowNum <= ' . $lastRow . ' ' . ' ) WHERE row_index >= ' . $firstRow;
         Horde::logMessage($psql . "\n" . print_r($values, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
         $beanClass = get_class($namedBean);
         $beanKey = $namedBean->get_bean_key();
         $resultSet = $db->query($psql, $values);
         if (is_a($resultSet, 'PEAR_Error')) {
             $listBean->setError($resultSet);
             QueryUtil::handleError($resultSet, $psql, $values, __LINE__);
             return false;
         }
         $row = $resultSet->fetchRow(DB_FETCHMODE_ASSOC);
         while (!empty($row)) {
             if (is_a($row, 'PEAR_Error')) {
                 $listBean->setError($row);
                 QueryUtil::handleError($row, $psql, $values, __LINE__);
                 return false;
             }
             if (is_array($beanKey)) {
                 $keyVars = array();
                 foreach ($beanKey as $key) {
                     $keyVars[] = $row[$key];
                 }
                 $listKey = join('|', $keyVars);
                 $list[$listKey] = new $beanClass($row);
             } else {
                 $list[$row[$beanKey]] = new $beanClass($row);
             }
             $row = $resultSet->fetchRow(DB_FETCHMODE_ASSOC);
         }
     } else {
         Horde::logMessage('No matching rows: ' . $sql, __FILE__, __LINE__, PEAR_LOG_INFO);
     }
     $listBean->set_list($list);
     global $dispatcher;
     $dispatcher->timers[__CLASS__][__FUNCTION__][] = Horde_Timer::singleton()->pop();
     return true;
 }