Example #1
0
 /**
  * Fetch results from a model
  *
  * @param array $options Various fetching options (e.g. limit, sorting, etc.)
  * @return array
  */
 public function fetch(array $options = null)
 {
     try {
         $this->_checkAcl('fetch');
     } catch (Garp_Auth_Exception $e) {
         $this->_checkAcl('fetch_own');
     }
     if ($this->_model instanceof Garp_Model_Db) {
         $options = $options instanceof Garp_Util_Configuration ? $options : new Garp_Util_Configuration($options);
         $options->setDefault('sort', array())->setDefault('start', null)->setDefault('limit', null)->setDefault('fields', null)->setDefault('query', false)->setDefault('group', array())->setDefault('rule', null)->setDefault('bindingModel', null)->setDefault('bidirectional', false)->setDefault('filterForeignKeys', false);
         $options['sort'] = (array) $options['sort'];
         $options['fields'] = (array) $options['fields'];
         $tableName = $this->_getTableName($this->_model);
         $options = (array) $options;
         $modelInfo = $this->_model->info();
         $referenceMap = $modelInfo['referenceMap'];
         // SELECT
         // ============================================================
         $select = $this->_model->select();
         $select->setIntegrityCheck(false);
         // FILTER WHERES AND JOINS
         // ============================================================
         $related = array();
         if ($options['query'] && !empty($options['query'])) {
             /**
              * Check for other model names in the conditions.
              * These are indicated by a dot (".") in the name.
              * If available, add these models as joins to the Select object.
              * The format is <related-model-name>.<primary-key> => <value>.
              */
             foreach ($options['query'] as $column => $value) {
                 if (strpos($column, '.') !== false) {
                     $related[$column] = $value;
                     unset($options['query'][$column]);
                 }
             }
         }
         // FROM
         // ============================================================
         if ($options['fields']) {
             $fields = $options['fields'];
         } elseif (count($related)) {
             // When using a join filter (used for the relationpanel), it's more performant to
             // specify only a model's list fields, otherwise the query can get pretty heavy for
             // tables with 100.000+ records.
             $primary = array_values($this->_model->info(Zend_Db_Table_Abstract::PRIMARY));
             $fields = array_merge($this->_model->getListFields(), $primary);
         } else {
             $fields = Zend_Db_Table_Select::SQL_WILDCARD;
         }
         // If filterForeignKeys is true, filter out the foreign keys
         if ($options['filterForeignKeys']) {
             $fields = $this->_filterForeignKeyColumns($fields, $referenceMap);
         }
         $select->from($tableName, $fields);
         // JOIN
         // ============================================================
         if (count($related)) {
             $this->_addJoinClause($select, $related, $options['rule'], $options['bindingModel'], $options['bidirectional']);
         }
         // WHERE
         // Add WHERE clause if there still remains something after
         // filtering.
         // ============================================================
         if ($options['query']) {
             $select->where($this->_createWhereClause($options['query']));
         }
         // GROUP
         // ============================================================
         $select->group($options['group']);
         // ORDER
         // ============================================================
         // Prefix native columns with the table name (e.g. "id" becomes
         // "Thing.id")
         // Note that we create a mock table object based on the joint view
         // to collect column info.
         // This should be more accurate than reading that info from the table.
         $mockTable = new Zend_Db_Table(array(Zend_Db_Table_Abstract::NAME => $tableName, Zend_Db_Table_Abstract::PRIMARY => $this->_model->info(Zend_Db_Table_Abstract::PRIMARY)));
         $nativeColumns = $mockTable->info(Zend_Db_Table_Abstract::COLS);
         $select->order(array_map(function ($s) use($tableName, $nativeColumns) {
             $nativeColTest = preg_replace('/(ASC|DESC)$/', '', $s);
             $nativeColTest = trim($nativeColTest);
             if (in_array($nativeColTest, $nativeColumns) && strpos($s, '.') === false) {
                 $s = $tableName . '.' . $s;
             }
             return $s;
         }, $options['sort']));
         // LIMIT
         // ============================================================
         // Do not limit when a COUNT(*) is performed, this skews results.
         $isCountQuery = count($fields) == 1 && !empty($fields[0]) && strtolower($fields[0]) == 'count(*)';
         if (!$isCountQuery) {
             $select->limit($options['limit'], $options['start']);
         }
         $results = $this->_model->fetchAll($select)->toArray();
     } else {
         $results = $this->_model->fetchAll();
     }
     foreach ($results as &$result) {
         foreach ($result as $column => $value) {
             if (strpos($column, '.') !== false) {
                 $keyParts = explode('.', $column, 2);
                 $newKey = $keyParts[1];
                 $relModelKey = Garp_Util_String::strReplaceOnce($this->_model->getNameWithoutNamespace(), '', $keyParts[0]);
                 $result['relationMetadata'][$relModelKey][$newKey] = $value;
                 unset($result[$column]);
             }
         }
     }
     return $results;
 }