/** * Get the max row id - used when requesting rowid=-2 to return the last recorded detailed view * * @return int max row id */ protected function getMaxRowId() { if (!$this->getForm()->record_in_database) { return $this->rowId; } $listModel = $this->getListModel(); $fabrikDb = $listModel->getDb(); $item = $listModel->getTable(); $k = FabrikString::safeNameQuote($item->db_primary_key); // @TODO JQuery this $fabrikDb->setQuery("SELECT MAX({$k}) FROM " . FabrikString::safeColName($item->db_table_name) . $listModel->buildQueryWhere()); return $fabrikDb->loadResult(); }
/** * Get the part of the sql statement that orders the table data * Since 3.0.7 caches the results as calling orderBy twice when using single ordering in admin module anules the user selected order by * * @param mixed $query False or a query object * * @throws ErrorException * * @return mixed string or query object - Ordering part of sql statement */ public function buildQueryOrder($query = false) { $sig = $query ? 1 : 0; if (!isset($this->orderBy)) { $this->orderBy = array(); } if (array_key_exists($sig, $this->orderBy)) { return $this->orderBy[$sig]; } $package = $this->app->getUserState('com_fabrik.package', 'fabrik'); $params = $this->getParams(); $input = $this->app->input; $formModel = $this->getFormModel(); $table = $this->getTable(); $db = $this->getDb(); $this->selectedOrderFields = array(); if ($this->outputFormat == 'fabrikfeed' || $this->outputFormat == 'feed') { $dateColId = (int) $params->get('feed_date', 0); $dateColElement = $formModel->getElement($dateColId, true); $dateCol = $db->qn($dateColElement->getFullName(false, false, false)); if ($dateColId !== 0) { $this->order_dir = 'DESC'; $this->order_by = $dateCol; if (!$query) { return "\n" . ' ORDER BY ' . $dateCol . ' DESC'; } else { $query->order($dateCol . ' DESC'); return $query; } } } $strOrder = ''; /** * When list reordered the controller runs order() and * stores the order settings in the session by calling setOrderByAndDir() * it then redirects to the list view and here all we need to do it get * those order settings from the session */ $elements = $this->getElements(); // Build the order by statement from the session $clearOrdering = (bool) $input->getInt('clearordering', false) && $input->get('task') !== 'order'; $singleOrdering = $this->singleOrdering(); foreach ($elements as $element) { $context = 'com_' . $package . '.list' . $this->getRenderContext() . '.order.' . $element->getElement()->id; if ($clearOrdering) { $this->session->set($context, null); } else { // $$$tom Added single-ordering option if (!$singleOrdering || $singleOrdering && $element->getElement()->id == $input->getInt('orderby')) { $dir = $this->session->get($context); if ($dir != '' && $dir != '-' && trim($dir) != 'Array') { $strOrder == '' ? $strOrder = "\n ORDER BY " : ($strOrder .= ','); $strOrder .= FabrikString::safeNameQuote($element->getOrderByName(), false) . ' ' . $dir; $orderByName = FabrikString::safeNameQuote($element->getOrderByName(), false); $this->orderEls[] = $orderByName; $this->orderDirs[] = $dir; $element->getAsField_html($this->selectedOrderFields, $aAsFields); if ($query !== false && is_object($query)) { $query->order($orderByName . ' ' . $dir); } } } else { $this->session->set($context, null); } } } $userHasOrdered = $strOrder == '' ? false : true; // If nothing found in session use default ordering (or that set by querystring) if (!$userHasOrdered) { $orderBys = explode(',', $input->getString('order_by', $input->getString('orderby', ''))); if ($orderBys[0] == '') { $orderBys = json_decode($table->order_by, true); } // $$$ not sure why, but sometimes $orderBys is NULL at this point. if (!isset($orderBys)) { $orderBys = array(); } // Covert ids to names (were stored as names but then stored as ids) foreach ($orderBys as &$orderBy) { if (is_numeric($orderBy)) { $elementModel = $formModel->getElement($orderBy, true); $orderBy = $elementModel ? $elementModel->getOrderByName() : $orderBy; } } $orderDirs = explode(',', $input->getString('order_dir', $input->getString('orderdir', ''))); if ($orderDirs[0] == '') { $orderDirs = json_decode($table->order_dir, true); } $els = $this->getElements('filtername'); if (!empty($orderBys)) { $bits = array(); $o = 0; foreach ($orderBys as $orderByRaw) { $dir = FArrayHelper::getValue($orderDirs, $o, 'desc'); // As we use getString() for query string, need to sanitize if (!in_array(strtolower($dir), array('asc', 'desc', '-'))) { throw new ErrorException('invalid order direction: ' . $dir, 500); } if ($orderByRaw !== '' && $dir != '-') { // $$$ hugh - getOrderByName can return a CONCAT, ie join element ... /* * $$$ hugh - OK, we need to test for this twice, because older elements * which get converted form names to ids above have already been run through * getOrderByName(). So first check here ... */ if (!JString::stristr($orderByRaw, 'CONCAT(') && !JString::stristr($orderByRaw, 'CONCAT_WS(')) { $orderByRaw = FabrikString::safeColName($orderByRaw); if (array_key_exists($orderByRaw, $els)) { $field = $els[$orderByRaw]->getOrderByName(); /* * $$$ hugh - ... second check for CONCAT, see comment above * $$$ @TODO why don't we just embed this logic in safeColName(), so * it recognizes a CONCAT and treats it accordingly? */ if (!JString::stristr($field, 'CONCAT(') && !JString::stristr($field, 'CONCAT_WS(')) { $field = FabrikString::safeColName($field); } $bits[] = " {$field} {$dir}"; $this->orderEls[] = $field; $this->orderDirs[] = $dir; } else { if (strstr($orderByRaw, '_raw`')) { $orderByRaw = FabrikString::safeColNameToArrayKey($orderByRaw); } $bits[] = " {$orderByRaw} {$dir}"; $this->orderEls[] = $orderByRaw; $this->orderDirs[] = $dir; } } else { // If it was a CONCAT(), just add it with no other checks or processing $bits[] = " {$orderByRaw} {$dir}"; $this->orderEls[] = $orderByRaw; $this->orderDirs[] = $dir; } } $o++; } if (!empty($bits)) { if (!$query || !is_object($query)) { $strOrder = "\n ORDER BY" . implode(',', $bits); } else { $query->order(implode(',', $bits)); } } } } $groupBy = $this->getGroupBy(); if ($groupBy !== '') { $groupByColName = FabrikString::safeColName($groupBy); if (!in_array($groupByColName, $this->orderEls)) { $strOrder == '' ? $strOrder = "\n ORDER BY " : ($strOrder .= ','); $strOrder .= $groupByColName . ' ASC'; $this->orderEls[] = $groupBy; $this->orderDirs[] = 'ASC'; if ($query !== false && is_object($query)) { $query->order(FabrikString::safeColName($groupBy) . ' ASC'); } } } /* apply group ordering * @TODO - explain something to hugh! Why is this "group ordering"? AFAICT, it's just a secondary * order by, isn't specific to the Group By feature in any way? So why not just put this option in */ $groupOrderBy = $params->get('group_by_order'); if ($groupOrderBy != '') { $groupOrderDir = $params->get('group_by_order_dir'); $strOrder == '' ? $strOrder = "\n ORDER BY " : ($strOrder .= ','); $orderBy = strstr($groupOrderBy, '_raw`') ? FabrikString::safeColNameToArrayKey($groupOrderBy) : FabrikString::safeColName($groupOrderBy); if (!$query) { $strOrder .= $orderBy . ' ' . $groupOrderDir; } else { $query->order($orderBy . ' ' . $groupOrderDir); } $this->orderEls[] = $orderBy; $this->orderDirs[] = $groupOrderDir; } $this->orderBy[$sig] = $query === false ? $strOrder : $query; return $this->orderBy[$sig]; }
/** * @param string $string Search string * @param FabrikTableJoin $join Join table * @param string $alias Table alias - defaults to the join->table_join_alias * * @return mixed */ protected function parseThisTable($string, $join = null, $alias = null) { if (is_null($join)) { $join = $this->getJoin(); } if (is_null($alias)) { $alias = $join->table_join_alias; } return str_replace('{thistable}', FabrikString::safeNameQuote($alias), $string); }