function display($tmpl = 'default') { FabrikHelperHTML::debug($this, 'view'); $records = JRequest::getVar('ids', array()); $renderOrder = JRequest::getVar('renderOrder'); $tableid = JRequest::getVar('id', 0); $this->assign('recordcount', count($records)); $this->assign('renderOrder', $renderOrder); $this->assign('recordids', implode(',', $records)); $this->assign('tableid', $tableid); $this->assign('fieldList', $this->get('ElementList', 'form')); JHTML::stylesheet('template.css', 'components/com_fabrik/plugins/table/emailtableplus/views/emailtableplus/tmpl/', true); //ensure we don't have an incorrect version of mootools loaded FabrikHelperHTML::cleanMootools(); if ($this->_isMambot) { return $this->loadTemplate(); } else { parent::display(); } }
function display($tmpl = 'default') { FabrikHelperHTML::debug($this, 'view'); $records = JRequest::getVar('ids', array()); $renderOrder = JRequest::getVar('renderOrder'); $tableid = JRequest::getVar('id', 0); $this->assign('recordcount', count($records)); $this->assign('renderOrder', $renderOrder); $this->assign('recordids', implode(',', $records)); $this->assign('tableid', $tableid); $this->assign('fieldList', $this->get('ElementList', 'form')); $this->assign('chown_to_select', JHTML::_('select.genericlist', $this->chown_to_options, 'chown_to_val', 'class="fabrikinput inputbox" size="1"', 'value', 'text', '', 'chown_to_val')); JHTML::stylesheet('template.css', 'components/com_fabrik/plugins/table/chown/views/chown/tmpl/', true); //ensure we don't have an incorrect version of mootools loaded FabrikHelperHTML::cleanMootools(); if ($this->_isMambot) { return $this->loadTemplate(); } else { parent::display(); } }
/** * Create the sql query used to get the join data * * @param array $data data * @param bool $incWhere include where * @param array $opts query options * * @return mixed JDatabaseQuery or false if query can't be built */ protected function _buildQuery($data = array(), $incWhere = true, $opts = array()) { $sig = isset($this->_autocomplete_where) ? $this->_autocomplete_where . '.' . $incWhere : $incWhere; $sig .= '.' . serialize($opts); $repeatCounter = JArrayHelper::getValue($opts, 'repeatCounter', 0); $db = FabrikWorker::getDbo(); if (isset($this->_sql[$sig])) { return $this->_sql[$sig]; } $params = $this->getParams(); $element = $this->getElement(); $watch = $this->getWatchFullName(); $whereval = null; $groups = $this->getForm()->getGroupsHiarachy(); foreach ($groups as $groupModel) { $elementModels = $groupModel->getPublishedElements(); foreach ($elementModels as $elementModel) { $fullName = $elementModel->getFullName(true, true, true); if ($fullName == $watch) { // Test for ajax update if (JRequest::getVar('fabrik_cascade_ajax_update') == 1) { $whereval = JRequest::getVar('v'); } else { if (isset($this->_form->_data) || isset($this->_form->_formData)) { if (isset($this->_form->_data)) { $whereval = $elementModel->getValue($this->_form->_data, $repeatCounter); } else { $whereval = $elementModel->getValue($this->_form->_formData, $repeatCounter); } /* $$$ hugh - temporary bandaid to fix 'array' issue in view=details * @TODO fix underlying cause in database join getValue * http://fabrikar.com/forums/showthread.php?p=63512#post63512 */ if (is_array($whereval)) { $whereval = JArrayHelper::getValue($whereval, 0); } elseif (!isset($whereval)) { $whereval = ''; } } else { // $$$ hugh - prolly rendering table view ... $watch_raw = $watch . '_raw'; if (isset($data[$watch_raw])) { $whereval = $data[$watch_raw]; } else { // $$$ hugh ::sigh:: might be coming in via swapLabelsForvalues in pre_process phase // and join array in data will have been flattened. So try regular element name for watch. $no_join_watch_raw = $elementModel->getFullName(false, true, false) . '_raw'; if (isset($data[$no_join_watch_raw])) { $whereval = $data[$no_join_watch_raw]; } else { // $$$ hugh - if watched element has no value, we have been selecting all rows from CDD table // but should probably select none. $whereval = ''; } } } } continue 2; } } } $where = ''; $wherekey = $params->get('cascadingdropdown_key'); if (!is_null($whereval) && $wherekey != '') { $whereBits = explode('___', $wherekey); $wherekey = array_pop($whereBits); $where = $wherekey . ' = ' . $db->quote($whereval); } $filter = $params->get('cascadingdropdown_filter'); /* $$$ hugh - temporary hack to work around this issue: * http://fabrikar.com/forums/showthread.php?p=71288#post71288 * ... which is basically that if they are using {placeholders} in their * filter query, there's no point trying to apply that filter if we * aren't in form view, for instance when building a search filter * or in table view when the cdd is in a repeat group, 'cos there won't * be any {placeholder} data to use. * So ... for now, if the filter contains {...}, and view!=form ... skip it * $$$ testing fix for the bandaid, ccd JS should not be submitting data from form */ if (trim($filter) != '') { $where .= $where == '' ? ' ' : ' AND '; $where .= $filter; } $w = new FabrikWorker(); // $$$ hugh - add some useful stuff to search data if (!is_null($whereval)) { $placeholders = array('whereval' => $whereval, 'wherekey' => $wherekey); } else { $placeholders = array(); } $join = $this->getJoin(); $where = str_replace("{thistable}", $join->table_join_alias, $where); if (!empty($this->_autocomplete_where)) { $where .= $where == '' ? ' AND ' . $this->_autocomplete_where : $this->_autocomplete_where; } $data = array_merge($data, $placeholders); $where = $w->parseMessageForPlaceHolder($where, $data); $table = $this->getDbName(); $key = FabrikString::safeColName($params->get('cascadingdropdown_id')); $key = str_replace($db->quoteName($table), $db->quoteName($join->table_join_alias), $key); $orderby = 'text'; $tables = $this->getForm()->getLinkedFabrikLists($params->get('join_db_name')); $listModel = JModel::getInstance('List', 'FabrikFEModel'); $val = $params->get('cascadingdropdown_label_concat'); if (!empty($val)) { $val = str_replace("{thistable}", $join->table_join_alias, $val); $val = $w->parseMessageForPlaceHolder($val, $data); $val = 'CONCAT(' . $val . ')'; $orderby = $val; } else { $val = FabrikString::safeColName($params->get($this->labelParam)); $val = preg_replace("#^`({$table})`\\.#", $db->quoteName($join->table_join_alias) . '.', $val); foreach ($tables as $tid) { $listModel->setId($tid); $listModel->getTable(); $formModel = $this->getForm(); $formModel->getGroupsHiarachy(); $orderby = $val; // See if any of the tables elements match the db joins val/text foreach ($groups as $groupModel) { $elementModels = $groupModel->getPublishedElements(); foreach ($elementModels as $elementModel) { $element = $elementModel->_element; if ($element->name == $val) { $val = $elementModel->modifyJoinQuery($val); } } } } } $val = str_replace($db->quoteName($table), $db->quoteName($join->table_join_alias), $val); $query = $db->getQuery(true); $query->select('DISTINCT(' . $key . ') AS value, ' . $val . 'AS text'); $desc = $params->get('cdd_desc_column', ''); if ($desc !== '') { $query->select(FabrikString::safeColName($desc) . ' AS description'); } $query->from($db->quoteName($table) . ' AS ' . $db->quoteName($join->table_join_alias)); $query->where(FabrikString::rtrimword($where)); if (!JString::stristr($where, 'order by')) { $query->order($orderby . ' ASC'); } $this->_sql[$sig] = $query; FabrikHelperHTML::debug($this->_sql[$sig]); return $this->_sql[$sig]; }
function getJSIcons() { $icons = array(); $w = new FabrikWorker(); $uri = JURI::getInstance(); $params = $this->getParams(); $templates = (array) $params->get('fb_gm_detailtemplate'); $listids = (array) $params->get('googlemap_table'); //images for file system $aIconImgs = (array) $params->get('fb_gm_iconimage'); //image from marker data $markerImages = (array) $params->get('fb_gm_iconimage2'); //specifed letter $letters = (array) $params->get('fb_gm_icon_letter'); $aFirstIcons = (array) $params->get('fb_gm_first_iconimage'); $aLastIcons = (array) $params->get('fb_gm_last_iconimage'); $titleElements = (array) $params->get('fb_gm_title_element'); $groupClass = (array) $params->get('fb_gm_group_class'); $c = 0; $this->recordCount = 0; $maxMarkers = $params->get('fb_gm_markermax', 0); if (count($listids) == 1) { $recLimit = $maxMarkers; } else { $recLimit = 0; } $limitMessageShown = false; $limitMessage = $params->get('fb_gm_markermax_message'); $groupedIcons = array(); $k = 0; foreach ($listids as $listid) { $template = JArrayHelper::getValue($templates, $c, ''); $listModel = $this->getlistModel($listid); $table = $listModel->getTable(); $mapsElements = $listModel->getElementsOfType('googlemap'); if (empty($mapsElements)) { JError::raiseError(500, JText::_('No google map element present in this list')); continue; } $coordColumn = $mapsElements[0]->getFullName(false, true, false) . "_raw"; //are we using random start location for icons? $listModel->_randomRecords = $params->get('fb_gm_random_marker') == 1 && $recLimit != 0 ? true : false; //used in table model setLimits JRequest::setVar('limit' . $listid, $recLimit); $listModel->setLimits(); $nav = $listModel->getPagination(0, 0, $recLimit); $data = $listModel->getData(); $this->txt = array(); $k = 0; foreach ($data as $groupKey => $group) { foreach ($group as $row) { $customimagefound = false; $iconImg = JArrayHelper::getValue($aIconImgs, $c, ''); if ($k == 0) { $firstIcon = JArrayHelper::getValue($aFirstIcons, $c, $iconImg); if ($firstIcon !== '') { $iconImg = $firstIcon; } } $v = $this->getCordsFromData($row->{$coordColumn}); if ($v == array(0, 0)) { continue; //dont show icons with no data } $rowdata = JArrayHelper::fromObject($row); $rowdata['rowid'] = $rowdata['__pk_val']; $html = $w->parseMessageForPlaceHolder($template, $rowdata); $titleElement = JArrayHelper::getValue($titleElements, $c, ''); $title = $titleElement == '' ? '' : strip_tags($row->{$titleElement}); // $$$ hugh - if they provided a template, lets assume they will handle the link themselves. // http://fabrikar.com/forums/showthread.php?p=41550#post41550 // $$$ hugh - at some point the fabrik_view / fabrik_edit links became optional if (empty($html) && (array_key_exists('fabrik_view', $rowdata) || array_key_exists('fabrik_edit', $rowdata))) { $html .= "<br />"; // use edit link by preference if (array_key_exists('fabrik_edit', $rowdata)) { $html .= $rowdata['fabrik_edit']; } else { $html .= $rowdata['fabrik_view']; } } $html = str_replace(array("\n\r"), "<br />", $html); $html = str_replace(array("\n", "\r"), "<br />", $html); $html = str_replace("'", '"', $html); $this->txt[] = $html; if ($iconImg == '') { $iconImg = JArrayHelper::getValue($markerImages, $c, ''); if ($iconImg != '') { $iconImg = JArrayHelper::getValue($rowdata, $iconImg, ''); //get the src preg_match('/src=["|\'](.*?)["|\']/', $iconImg, $matches); if (array_key_exists(1, $matches)) { $iconImg = $matches[1]; //check file exists $path = str_replace(COM_FABRIK_LIVESITE, '', $iconImg); if (JFile::exists(JPATH_BASE . $path)) { $customimagefound = true; } } } if ($iconImg != '') { list($width, $height) = $this->markerSize($iconImg); } else { //standard google map icon size $width = 20; $height = 34; } } else { //standard google map icon size list($width, $height) = $this->markerSize(JPATH_SITE . DS . 'images' . DS . 'stories' . DS . $iconImg); } //just for moosehunt! $radomize = $_SERVER['HTTP_HOST'] == 'moosehunt.mobi' ? true : false; $groupKey = strip_tags($groupKey); $gClass = JArrayHelper::getValue($groupClass, 0, ''); if (!empty($gClass)) { $gClass .= '_raw'; $gClass = isset($row->{$gClass}) ? $row->{$gClass} : ''; } if (array_key_exists($v[0] . $v[1], $icons)) { $existingIcon = $icons[$v[0] . $v[1]]; if ($existingIcon['groupkey'] == $groupKey) { // $$$ hugh - this inserts label between multiple record $html, but not at the top. // If they want to insert label, they can do it themselves in the template. // $icons[$v[0].$v[1]][2] = $icons[$v[0].$v[1]][2] . "<h6>$table->label</h6>" . $html; $icons[$v[0] . $v[1]][2] = $icons[$v[0] . $v[1]][2] . "<br />" . $html; if ($customimagefound) { //$icons[$v[0].$v[1]][3] = "<br />" . $iconImg; $icons[$v[0] . $v[1]][3] = $iconImg; } } else { $groupedIcons[] = array($v[0], $v[1], $html, $iconImg, $width, $height, 'groupkey' => $groupKey, 'listid' => $listid, 'title' => $title, 'groupClass' => 'type' . $gClass); } } else { //default icon - lets see if we need to use a letterd icon instead if (JArrayHelper::getValue($letters, $c, '') != '') { $iconImg = $uri->getScheme() . '://www.google.com/mapfiles/marker' . strtoupper($letters[$c]) . '.png'; } $icons[$v[0] . $v[1]] = array($v[0], $v[1], $html, $iconImg, $width, $height, 'groupkey' => $groupKey, 'listid' => $listid, 'title' => $title, 'groupClass' => 'type' . $gClass); } $this->recordCount++; $k++; } } //replace last icon? $iconImg = JArrayHelper::getValue($aLastIcons, $c, ''); if ($iconImg != '') { list($width, $height) = $this->markerSize(JPATH_SITE . '/media/com_fabrik/images/' . $iconImg); $icons[$v[0] . $v[1]][3] = $iconImg; $icons[$v[0] . $v[1]][4] = $width; $icons[$v[0] . $v[1]][5] = $height; } $c++; } $icons = array_values($icons); //replace coord keys with numeric keys $icons = array_merge($icons, $groupedIcons); if ($maxMarkers != 0 && $maxMarkers < count($icons)) { $icons = array_slice($icons, -$maxMarkers); } $limitMessageShown = !($k >= $recLimit); if (!$limitMessageShown && $recLimit !== 0 && $limitMessage != '') { $app->enqueueMessage($limitMessage); } FabrikHelperHTML::debug($icons, 'map'); return $icons; }
/** * Main setup routine for displaying the form/detail view * * @param string $tpl template * * @return void */ public function display($tpl = null) { $profiler = JProfiler::getInstance('Application'); $input = $this->app->input; $w = new FabrikWorker(); /** @var FabrikFEModelForm $model */ $model = $this->getModel('form'); if (!$model) { // Dodgy URL - can't find the form name see https://github.com/Fabrik/fabrik/issues/1248 return; } $model->isMambot = $this->isMambot; $form = $model->getForm(); if ($model->render() === false) { return false; } $this->isMultiPage = $model->isMultiPage(); list($this->plugintop, $this->pluginbottom, $this->pluginend) = $model->getFormPluginHTML(); $listModel = $model->getlistModel(); if (!$model->canPublish()) { if (!$this->app->isAdmin()) { echo FText::_('COM_FABRIK_FORM_NOT_PUBLISHED'); return false; } } $this->rowid = $model->getRowId(); $this->access = $model->checkAccessFromListSettings(); if ($this->access == 0) { $this->app->enqueueMessage(FText::_('JERROR_ALERTNOAUTHOR'), 'error'); return false; } JDEBUG ? $profiler->mark('form view before join group ids got') : null; if (!$listModel->noTable()) { $joins = $listModel->getJoins(); $model->getJoinGroupIds($joins); } $params = $model->getParams(); $this->setTitle($w, $params); $this->setCanonicalLink($model); FabrikHelperHTML::debug($params->get('note'), 'note'); $params->def('icons', $this->app->get('icons')); $params->set('popup', $input->get('tmpl') == 'component' ? 1 : 0); $this->editable = $model->isEditable(); $form->label = FText::_($model->getLabel()); $form->intro = FText::_($model->getIntro()); $form->outro = FText::_($model->getOutro()); $form->action = $model->getAction(); $form->class = $model->getFormClass(); $form->formid = $model->isEditable() ? 'form_' . $model->getId() : 'details_' . $model->getId(); $form->name = 'form_' . $model->getId(); if ((string) $this->rowid !== '') { $form->formid .= '_' . $this->rowid; } $form->error = $form->error === '' ? FText::_('COM_FABRIK_FAILED_VALIDATION') : FText::_($form->error); if (!empty($model->formErrorMsg)) { $form->error .= '<br />' . $model->formErrorMsg; } $form->origerror = $form->error; $clearErrors = false; // Module rendered without ajax, we need to assign the session errors back into the model if ($model->isMambot) { $this->package = $this->app->getUserState('com_fabrik.package', 'fabrik'); $context = 'com_' . $this->package . '.form.' . $form->id . '.' . $this->rowid . '.'; $model->errors = $this->session->get($context . 'errors', array()); $clearErrors = true; } $form->error = $model->hasErrors() ? $form->error : ''; JDEBUG ? $profiler->mark('form view before validation classes loaded') : null; $tmpl = $model->getTmpl(); $this->tmpl = $tmpl; $this->_addButtons(); JDEBUG ? $profiler->mark('form view before group view got') : null; $this->groups = $model->getGroupView($tmpl); $btnData = new stdClass(); $l = FabrikHelperHTML::getLayout('form.fabrik-repeat-group-delete'); $this->removeRepeatGroupButton = $l->render($btnData); $l = FabrikHelperHTML::getLayout('form.fabrik-repeat-group-add'); $this->addRepeatGroupButton = $l->render($btnData); JDEBUG ? $profiler->mark('form view after group view got') : null; $this->data = $model->tmplData; $this->params = $params; $this->tipLocation = $params->get('tiplocation'); FabrikHelperHTML::debug($this->groups, 'form:view:groups'); // Force front end templates $this->_basePath = COM_FABRIK_FRONTEND . '/views'; $this->_addJavascript($listModel->getId()); JDEBUG ? $profiler->mark('form view: after add js') : null; $this->_loadTmplBottom($form); JDEBUG ? $profiler->mark('form view: after tmpl bottom loaded') : null; $form->attribs = ' class="' . $form->class . '" name="' . $form->name . '" id="' . $form->formid . '" enctype="' . $model->getFormEncType() . '"'; $this->form = $form; JDEBUG ? $profiler->mark('form view: form assigned as ref') : null; $list = new stdClass(); $list->id = $form->record_in_database ? $model->getListModel()->getTable()->id : 0; $this->list = $list; JDEBUG ? $profiler->mark('form view: before getRelatedTables()') : null; $this->linkedTables = $model->getRelatedTables(); JDEBUG ? $profiler->mark('form view: after getRelatedTables()') : null; $this->setMessage(); $jTmplFolder = FabrikWorker::j3() ? 'tmpl' : 'tmpl25'; $folder = $model->isEditable() ? 'form' : 'details'; $this->addTemplatePath($this->_basePath . '/' . $folder . '/' . $jTmplFolder . '/' . $tmpl); $root = $this->app->isAdmin() ? JPATH_ADMINISTRATOR : JPATH_SITE; $this->addTemplatePath($root . '/templates/' . $this->app->getTemplate() . '/html/com_fabrik/' . $folder . '/' . $tmpl); // If rendered as a module (non ajax) and we have inserted the session errors, clear them from the session. if ($clearErrors) { $model->clearErrors(); } JDEBUG ? $profiler->mark('form view before template load') : null; }
/** * main method to get the data to insert into the form * @return array form's data */ function getData() { //if already set return it. If not was causing issues with the juser form plugin // when it tried to modify the form->_data info, from within its onLoad method, when sync user option turned on. if (isset($this->_data)) { return $this->_data; } $profiler = JProfiler::getInstance('Application'); $this->_data = array(); $data = array(FArrayHelper::toObject(JRequest::get('request'))); $form = $this->getForm(); $aGroups = $this->getGroupsHiarachy(); JDEBUG ? $profiler->mark('formmodel getData: groups loaded') : null; if (!$form->record_in_database) { FabrikHelperHTML::debug($data, 'form:getData from $_REQUEST'); $data = JRequest::get('request'); } else { $listModel = $this->getListModel(); $fabrikDb = $listModel->getDb(); JDEBUG ? $profiler->mark('formmodel getData: db created') : null; $item = $listModel->getTable(); JDEBUG ? $profiler->mark('formmodel getData: table row loaded') : null; $this->_aJoinObjs =& $listModel->getJoins(); JDEBUG ? $profiler->mark('formmodel getData: joins loaded') : null; if (!empty($this->_arErrors)) { // $$$ hugh - if we're a mambot, reload the form session state we saved in // process() when it banged out. if ($this->isMambot) { $srow = $this->getSessionData(); $this->sessionModel->last_page = 0; if ($srow->data != '') { $data = FArrayHelper::toObject(unserialize($srow->data), 'stdClass', false); JFilterOutput::objectHTMLSafe($data); $data = array($data); FabrikHelperHTML::debug($data, 'form:getData from session (form in Mambot and errors)'); } } else { // $$$ rob - use setFormData rather than JRequest::get() //as it applies correct input filtering to data as defined in article manager parameters $data = $this->setFormData(); $data = FArrayHelper::toObject($data, 'stdClass', false); //$$$rob ensure "<tags>text</tags>" that are entered into plain text areas are shown correctly JFilterOutput::objectHTMLSafe($data); $data = array($data); FabrikHelperHTML::debug($data, 'form:getData from POST (form not in Mambot and errors)'); } } else { //test if its a resumed paged form $srow = $this->getSessionData(); JDEBUG ? $profiler->mark('formmodel getData: session data loaded') : null; if ($this->saveMultiPage() && $srow->data != '') { $data = array(FArrayHelper::toObject(array_merge(unserialize($srow->data), JArrayHelper::fromObject($data[0])))); FabrikHelperHTML::debug($data, 'form:getData from session (form not in Mambot and no errors'); } else { // only try and get the row data if its an active record //use !== 0 as rowid may be alphanumeric // $$$ hugh - when 'usekey', rowid can actually be 0 (like if using userid and this is guest access) // so go ahead and try and load the row, if it doesn't exist, we'll supress the warning $usekey = FabrikWorker::getMenuOrRequestVar('usekey', '', $this->isMambot); if (!empty($usekey) || (int) $this->_rowId !== 0 || !is_numeric($this->_rowId) && $this->_rowId != '') { // $$$ hugh - once we have a few join elements, our select statements are // getting big enough to hit default select length max in MySQL. $listModel->setBigSelects(); //otherwise lets get the table record $sql = $this->_buildQuery(); $fabrikDb->setQuery($sql); FabrikHelperHTML::debug($fabrikDb->getQuery(), 'form:render'); $rows = $fabrikDb->loadObjectList(); if (is_null($rows)) { JError::raiseWarning(500, $fabrikDb->getErrorMsg()); } JDEBUG ? $profiler->mark('formmodel getData: rows data loaded') : null; //$$$ rob Ack above didnt work for joined data where there would be n rows rerutned frho "this rowid = $this->_rowId \n"; if (!empty($rows)) { // only do this if the query returned some rows (it wont if usekey on and userid = 0 for example) $data = array(); foreach ($rows as &$row) { if (empty($data)) { //if loading in a rowid=-1 set the row id to the actual row id $this->_rowId = isset($row->__pk_val) ? $row->__pk_val : $this->_rowId; } $row = empty($row) ? array() : JArrayHelper::fromObject($row); $data[] = FArrayHelper::toObject(array_merge($row, JRequest::get('request'))); } } FabrikHelperHTML::debug($data, 'form:getData from querying rowid= ' . $this->_rowId . ' (form not in Mambot and no errors)'); // if empty data return and trying to edit a record then show error //occurs if user trying to edit a record forbidden by a prefilter rull if (empty($data) && $this->_rowId != '') { // $$$ hugh - special case when using -1, if user doesn't have a record yet if (FabrikWorker::getMenuOrRequestVar('rowid', '', $this->isMambot) == '-1') { return; } else { // if no key found set rowid to 0 so we can insert a new record. if (empty($usekey) && !$this->isMambot) { $this->_rowId = 0; JError::raiseNotice(500, JText::sprintf('COULD NOT FIND RECORD IN DATABASE', $this->_rowId)); return; } else { //if we are using usekey then theres a good possiblity that the record //won't yet exists- so in this case suppress this error message $this->_rowId = 0; } } } } } //no need to setJoinData if you are correcting a failed validation if (!empty($data)) { $this->setJoinData($data); } } //set the main part of the form's default data if ($this->_rowId != '') { $data = JArrayHelper::fromObject($data[0]); } else { //could be a view if ($listModel->isView()) { //@TODO test for new records from views $data = JArrayHelper::fromObject($data[0]); } else { if (($this->isMambot || $this->saveMultiPage()) && (!empty($data) && is_object($data[0]))) { $data = JArrayHelper::fromObject($data[0]); } else { // $$$ rob was causing notices when adding record with joined groups as $data[0]->join unset if we just use request //$data = JRequest::get('request'); $data = JArrayHelper::fromObject($data[0]); } } } $this->_listModel = $listModel; } //Test to allow {$my->id}'s to be evald from query strings $w = new FabrikWorker(); $data = $w->parseMessageForPlaceHolder($data); $this->_data = $data; FabrikHelperHTML::debug($data, 'form:data'); JDEBUG ? $profiler->mark('queryselect: getData() end') : null; return $this->_data; }
/** * Main method to get the data to insert into the form * * @return array Form's data */ public function getData() { // If already set return it. If not was causing issues with the juser form plugin // when it tried to modify the form->data info, from within its onLoad method, when sync user option turned on. if (isset($this->data)) { return $this->data; } $this->getRowId(); $input = $this->app->input; $profiler = JProfiler::getInstance('Application'); JDEBUG ? $profiler->mark('formmodel getData: start') : null; $this->data = array(); $f = JFilterInput::getInstance(); /* * $$$ hugh - we need to remove any elements from the query string, * if the user doesn't have access, otherwise ACL's on elements can * be bypassed by just setting value on form load query string! */ $clean_request = $f->clean($_REQUEST, 'array'); foreach ($clean_request as $key => $value) { $test_key = FabrikString::rtrimword($key, '_raw'); $elementModel = $this->getElement($test_key, false, false); if ($elementModel !== false) { if (!$elementModel->canUse()) { unset($clean_request[$key]); } } } $data = $clean_request; $form = $this->getForm(); $this->getGroupsHiarachy(); JDEBUG ? $profiler->mark('formmodel getData: groups loaded') : null; if (!$form->record_in_database) { FabrikHelperHTML::debug($data, 'form:getData from $_REQUEST'); $data = $f->clean($_REQUEST, 'array'); } else { JDEBUG ? $profiler->mark('formmodel getData: start get list model') : null; $listModel = $this->getListModel(); JDEBUG ? $profiler->mark('formmodel getData: end get list model') : null; $fabrikDb = $listModel->getDb(); JDEBUG ? $profiler->mark('formmodel getData: db created') : null; $listModel->getTable(); JDEBUG ? $profiler->mark('formmodel getData: table row loaded') : null; $this->aJoinObjs = $listModel->getJoins(); JDEBUG ? $profiler->mark('formmodel getData: joins loaded') : null; if ($this->hasErrors()) { // $$$ hugh - if we're a mambot, reload the form session state we saved in // process() when it banged out. if ($this->isMambot) { $sessionRow = $this->getSessionData(); $this->sessionModel->last_page = 0; if ($sessionRow->data != '') { $sData = unserialize($sessionRow->data); $data = FArrayHelper::toObject($sData, 'stdClass', false); JFilterOutput::objectHTMLSafe($data); $data = array($data); FabrikHelperHTML::debug($data, 'form:getData from session (form in Mambot and errors)'); } } else { // $$$ rob - use setFormData rather than $_GET // as it applies correct input filtering to data as defined in article manager parameters $data = $this->setFormData(); $data = FArrayHelper::toObject($data, 'stdClass', false); // $$$rob ensure "<tags>text</tags>" that are entered into plain text areas are shown correctly JFilterOutput::objectHTMLSafe($data); $data = ArrayHelper::fromObject($data); FabrikHelperHTML::debug($data, 'form:getData from POST (form not in Mambot and errors)'); } } else { $sessionLoaded = false; // Test if its a resumed paged form if ($this->saveMultiPage()) { $sessionRow = $this->getSessionData(); JDEBUG ? $profiler->mark('formmodel getData: session data loaded') : null; if ($sessionRow->data != '') { $sessionLoaded = true; /* * $$$ hugh - this chunk should probably go in setFormData, but don't want to risk any side effects just now * problem is that later failed validation, non-repeat join element data is not formatted as arrays, * but from this point on, code is expecting even non-repeat join data to be arrays. */ $tmp_data = unserialize($sessionRow->data); $groups = $this->getGroupsHiarachy(); foreach ($groups as $groupModel) { if ($groupModel->isJoin() && !$groupModel->canRepeat()) { foreach ($tmp_data['join'][$groupModel->getJoinId()] as &$el) { $el = array($el); } } } $bits = $data; $bits = array_merge($tmp_data, $bits); //$data = array(FArrayHelper::toObject($bits)); $data = $bits; FabrikHelperHTML::debug($data, 'form:getData from session (form not in Mambot and no errors'); } } if (!$sessionLoaded) { /* Only try and get the row data if its an active record * use !== '' as rowid may be alphanumeric. * Unlike 3.0 rowId does equal '' if using rowid=-1 and user not logged in */ $useKey = FabrikWorker::getMenuOrRequestVar('usekey', '', $this->isMambot); if (!empty($useKey) || $this->rowId !== '') { // $$$ hugh - once we have a few join elements, our select statements are // getting big enough to hit default select length max in MySQL. $listModel->setBigSelects(); // Otherwise lets get the table record /** * $$$ hugh - 11/14/2015 - ran into issue with the order by from a list being added to the form query, when * rendering a form with a content plugin in a list intro. And I don't think we ever need to * apply ordering to a form's select, by definition it's only one row. Leaving this here for * now just as a reminder in case there's any unforeseen side effects. * * $$$ hugh - 4/25/2016 - yes, there is an issue, as (duh!) ordering is needed for repeat groups. * Changing this back to original for now, will need to work out how to handle that corner case */ $opts = $input->get('task') == 'form.inlineedit' ? array('ignoreOrder' => true) : array(); // $opts = array('ignoreOrder' => true); $sql = $this->buildQuery($opts); $fabrikDb->setQuery($sql); FabrikHelperHTML::debug((string) $fabrikDb->getQuery(), 'form:render'); $rows = $fabrikDb->loadObjectList(); if (is_null($rows)) { JError::raiseWarning(500, $fabrikDb->getErrorMsg()); } JDEBUG ? $profiler->mark('formmodel getData: rows data loaded') : null; // $$$ rob Ack above didn't work for joined data where there would be n rows returned for "this rowid = $this->rowId \n"; if (!empty($rows)) { // Only do this if the query returned some rows (it wont if usekey on and userid = 0 for example) $data = array(); foreach ($rows as &$row) { if (empty($data)) { // If loading in a rowid=-1 set the row id to the actual row id $this->rowId = isset($row->__pk_val) ? $row->__pk_val : $this->rowId; } $row = empty($row) ? array() : ArrayHelper::fromObject($row); $request = $clean_request; $request = array_merge($row, $request); $data[] = FArrayHelper::toObject($request); } } FabrikHelperHTML::debug($data, 'form:getData from querying rowid= ' . $this->rowId . ' (form not in Mambot and no errors)'); // If empty data return and trying to edit a record then show error JDEBUG ? $profiler->mark('formmodel getData: empty test') : null; // Was empty($data) but that is never empty. Had issue where list prefilter meant record was not loaded, but no message shown in form if (empty($rows) && $this->rowId != '') { // $$$ hugh - special case when using -1, if user doesn't have a record yet if ($this->isUserRowId()) { return; } else { // If no key found set rowid to 0 so we can insert a new record. if (empty($useKey) && !$this->isMambot && in_array($input->get('view'), array('form', 'details'))) { $this->rowId = ''; /** * runtime exception is a little obtuse for people getting here from legitimate links, * like from an email, but aren't logged in so run afoul of a pre-filter, etc * So do the 3.0 thing, and raise a warning */ //throw new RuntimeException(FText::_('COM_FABRIK_COULD_NOT_FIND_RECORD_IN_DATABASE')); JError::raiseWarning(500, FText::_('COM_FABRIK_COULD_NOT_FIND_RECORD_IN_DATABASE')); } else { // If we are using usekey then there's a good possibility that the record // won't yet exist - so in this case suppress this error message $this->rowId = ''; } } } } } // No need to setJoinData if you are correcting a failed validation if (!empty($data)) { $this->setJoinData($data); } } } $this->data = $data; FabrikHelperHTML::debug($data, 'form:data'); JDEBUG ? $profiler->mark('queryselect: getData() end') : null; return $this->data; }
/** * Filter the list data * * @return null */ public function filter() { $app = JFactory::getApplication(); $input = $app->input; $modelName = $input->get('view', 'list'); $model = $this->getModel($modelName, 'FabrikFEModel'); $model->setId($input->getInt('listid')); FabrikHelperHTML::debug('', 'list model: getRequestData'); $request = $model->getRequestData(); $model->storeRequestData($request); // $$$ rob pass in the model otherwise display() rebuilds it and the request data is rebuilt return $this->display($model); }
/** * Create an array of label/values which will be used to populate the elements filter dropdown * returns all possible options * * @param bool $normal do we render as a normal filter or as an advanced search filter * @param string $tableName table name to use - defaults to element's current table * @param string $label field to use, defaults to element name * @param string $id field to use, defaults to element name * @param bool $incjoin include join * * @return array filter value and labels */ protected function filterValueList_All($normal, $tableName = '', $label = '', $id = '', $incjoin = true) { if ($this->isJoin()) { $rows = array_values($this->checkboxRows()); return $rows; } /* * list of all tables that have been joined to - * if duplicated then we need to join using a table alias */ $listModel = $this->getlistModel(); $table = $listModel->getTable(); $origTable = $table->db_table_name; $fabrikDb = $listModel->getDb(); $params = $this->getParams(); $joinTable = $params->get('join_db_name'); $joinKey = $this->getJoinValueColumn(); $joinVal = $this->getJoinLabelColumn(); $join = $this->getJoin(); $joinTableName = $join->table_join_alias; if ($joinTable == '') { $joinTable = $joinTableName; } // $$$ hugh - select all values for performance gain over selecting distinct records from recorded data $sql = "SELECT DISTINCT( {$joinVal} ) AS text, {$joinKey} AS value \n FROM " . $fabrikDb->quoteName($joinTable) . ' AS ' . $fabrikDb->quoteName($joinTableName) . " \n "; $where = $this->buildQueryWhere(array(), true, null, array('mode' => 'filter')); // Ensure table prefilter is applied to query $prefilterWhere = $listModel->buildQueryPrefilterWhere($this); $elementName = FabrikString::safeColName($this->getFullName(false, false)); $prefilterWhere = str_replace($elementName, $joinKey, $prefilterWhere); if (trim($where) == '') { /* $$$ hugh - Sanity check - won't this screw things up if we have a complex prefilter with multiple filters using AND grouping? */ $prefilterWhere = str_replace('AND', 'WHERE', $prefilterWhere); } $where .= $prefilterWhere; $sql .= $where; if (!JString::stristr($where, 'order by')) { $sql .= $this->getOrderBy('filter'); } $sql = $listModel->pluginQuery($sql); $fabrikDb->setQuery($sql); FabrikHelperHTML::debug($fabrikDb->getQuery(), 'fabrikdatabasejoin getFilter'); return $fabrikDb->loadObjectList(); }
/** * overwrite session and serach all filters with posted data * @param $filters */ private function getPostFilters(&$filters) { $item = $this->listModel->getTable(); $request = $this->getPostFilterArray(); $elements = $this->listModel->getElements('id'); $filterkeys = array_keys($filters); $values = JArrayHelper::getValue($request, 'value', array()); $searchTypes = JArrayHelper::getValue($filters, 'search_type', array()); $usedMerges = array(); if (!empty($request) && array_key_exists('key', $request)) { $keyints = array_keys($request['key']); //for ($i = 0; $i < count($request['key']); $i++) { // $$$ rob - in default_horiz_search tmpl only filters whose elements are set to show in list are shown // thus the filters may be keyed non-sequentially. Use $keyints rather than count($request[$key]) to ensure // that $key is found $ajaxPost = strtolower(JRequest::getVar('HTTP_X_REQUESTED_WITH', '', 'server')); $this->listModel->ajaxPost = $ajaxPost; $this->listModel->postValues = $values; foreach ($keyints as $i) { $value = JArrayHelper::getValue($values, $i, ''); // $$$ rob 28/10/2011 - running an ajax filter (autocomplete) from horz-search tmpl, looking for term 'test + test' // the '+' is converted into a space so search fails /* if ($ajaxPost == 'xmlhttprequest') { if (is_array($value)) { foreach ($value as $k => $v) { $value[$k] = urldecode($v); } } else { $value = urldecode($value); } } */ $key = JArrayHelper::getValue($request['key'], $i); $elid = JArrayHelper::getValue($request['elementid'], $i); if ($key == '') { continue; } // index is the filter index for a previous filter that uses the same element id if (!in_array($elid, $usedMerges)) { $index = array_key_exists('elementid', $filters) ? array_search($elid, (array) $filters['elementid']) : false; } else { $index = false; } if ($index !== false) { $usedMerges[] = $elid; } //rob empty post filters SHOULD overwrite previous filters, as the user has submitted // this filter with nothing selected /*if (is_string($value) && trim($value) == '') { continue; } */ // $$$ rob set a var for empty value - regardless of whether its an array or string $emptyValue = is_string($value) && trim($value) == '' || is_array($value) && trim(implode('', $value)) == ''; // $$rob ok the above meant that require filters stopped working as soon as you submitted // an empty search! // So now add in the empty search IF there is NOT a previous filter in the search data if ($emptyValue && $index === false) { continue; } // $$$ rob if we are posting an empty value then we really have to clear the filter out from the // session. Otherwise the filter is run as "where field = ''" if ($emptyValue && $index !== false) { // $$ $rob - if the filter has been added from search all then don't remove it if (JArrayHelper::getValue($searchTypes, $index) != 'searchall') { $this->clearAFilter($filters, $index); } // $$$ rob - regardless of whether the filter was added by search all or not - don't overwrite it with post filter continue; } $elementModel = $elements[$elid]; if (!is_a($elementModel, 'plgFabrik_Element')) { continue; } //if the request key is already in the filter array - unset it if ($index !== false) { foreach ($filterkeys as $fkey) { if (is_array($filters[$fkey]) && array_key_exists($index, $filters[$fkey])) { // don't unset search all filters when the value is empty and continue so we dont add in a new filter //if (array_key_exists($index, $filters['search_type']) && ($filters['search_type'][$index] == 'searchall' && $value == '')) { if (JArrayHelper::getValue($searchTypes, $index) == 'searchall' && $value == '') { continue 2; } //$$$rob we DO need to unset unset($filters[$fkey][$index]); } } } //empty ranged data test // $$$ hugh - was getting single value array when testing AJAX nav, so 'undefined index 1' warning. if (is_array($value) && $value[0] == '' && (!isset($value[1]) || $value[1] == '')) { continue; } $eval = is_array($value) ? JArrayHelper::getValue($value, 'eval', FABRIKFILTER_TEXT) : FABRIKFILTER_TEXT; if (!is_a($elementModel, 'plgFabrik_ElementDatabasejoin')) { $fieldDesc = $elementModel->getFieldDescription(); if (JString::stristr($fieldDesc, 'INT')) { if (is_numeric($value) && $request['condition'][$i] == '=') { $eval = FABRKFILTER_NOQUOTES; } } } // $$$ rob - search all and dropdown filter: Search first on searchall = usa, then select dropdown to usa. // post filter query overwrites search all query, but uses add so = where id REGEX 'USA' AND country LIKE '%USA' // this code swaps the first $joinMode = strtolower($request['join'][$i]) != 'where' ? $request['join'][$i] : 'AND'; if (!empty($filters)) { if ($i == 0) { $joinMode = array_pop(JArrayHelper::getValue($filters, 'join', array('AND'))); // $$$ rob - If search all made, then the post filters should filter further the results $lastSearchType = array_pop(JArrayHelper::getValue($filters, 'search_type', array('normal'))); if ($lastSearchType == 'searchall') { $joinMode = 'AND'; } } } //add request filter to end of filter array $element = $elementModel->getElement(); $elparams = $elementModel->getParams(); $filters['value'][] = $value; $filters['condition'][] = urldecode($request['condition'][$i]); $filters['join'][] = $joinMode; $filters['no-filter-setup'][] = $element->filter_type == '' ? 1 : 0; $filters['hidden'][] = $element->filter_type == '' ? 1 : 0; $filters['key'][] = urldecode($key); $filters['search_type'][] = JArrayHelper::getValue($request['search_type'], $i, 'normal'); $filters['match'][] = $element->filter_exact_match; $filters['full_words_only'][] = $elparams->get('full_words_only'); $filters['eval'][] = $eval; $filters['required'][] = $elparams->get('filter_required'); $filters['access'][] = $elparams->get('filter_access'); $filters['grouped_to_previous'][] = JArrayHelper::getValue($request['grouped_to_previous'], $i, '0'); $filters['label'][] = $elparams->get('alt_list_heading') == '' ? $element->label : $elparams->get('alt_list_heading'); $filters['elementid'][] = $elid; $filters['raw'][] = false; } } $this->listModel->tmpFilters = $filters; FabrikHelperHTML::debug($filters, 'filter array: before onGetPostFilter'); FabrikWorker::getPluginManager()->runPlugins('onGetPostFilter', $this->listModel, 'list', $filters); FabrikHelperHTML::debug($filters, 'filter array: after onGetPostFilter'); $filters = $this->listModel->tmpFilters; }
/** * Main setup routine for displaying the form/detail view * * @param string $tpl template * * @return void */ public function display($tpl = null) { $profiler = JProfiler::getInstance('Application'); $app = JFactory::getApplication(); $w = new FabrikWorker(); $config = JFactory::getConfig(); $model = $this->getModel('form'); $document = JFactory::getDocument(); $model->isMambot = $this->isMambot; $form = $model->getForm(); if ($model->render() === false) { return false; } $this->isMultiPage = $model->isMultiPage(); list($this->plugintop, $this->pluginbottom, $this->pluginend) = $this->get('FormPluginHTML'); $listModel = $model->getlistModel(); $table = $listModel->noTable() ? null : $listModel->getTable(); if (!$model->canPublish()) { if (!$app->isAdmin()) { echo JText::_('COM_FABRIK_FORM_NOT_PUBLISHED'); return false; } } $this->assign('rowid', $model->_rowId); $this->assign('access', $model->checkAccessFromListSettings()); if ($this->access == 0) { return JError::raiseWarning(500, JText::_('JERROR_ALERTNOAUTHOR')); } JDEBUG ? $profiler->mark('form view before join group ids got') : null; if (!$listModel->noTable()) { $joins = $listModel->getJoins(); $model->getJoinGroupIds($joins); } $params = $model->getParams(); $this->setTitle($w, $params, $model); FabrikHelperHTML::debug($params->get('note'), 'note'); $params->def('icons', $app->getCfg('icons')); $params->set('popup', JRequest::getVar('tmpl') == 'component' ? 1 : 0); $this->editable = $model->isEditable(); $form->label = $this->get('label'); $form->intro = $model->getIntro(); $form->outro = $model->getOutro(); $form->action = $this->get('Action'); $form->formid = $model->isEditable() ? 'form_' . $model->getId() : 'details_' . $model->getId(); $form->name = 'form_' . $model->getId(); if ($form->error === '') { $form->error = JText::_('COM_FABRIK_FAILED_VALIDATION'); } $form->origerror = $form->error; $form->error = $model->hasErrors() ? $form->error : ''; JDEBUG ? $profiler->mark('form view before validation classes loaded') : null; $tmpl = $this->get('tmpl'); $this->assign('tmpl', $tmpl); $this->_addButtons(); JDEBUG ? $profiler->mark('form view before group view got') : null; $this->groups = $model->getGroupView($tmpl); JDEBUG ? $profiler->mark('form view after group view got') : null; $this->assignRef('data', $model->data); $this->assignRef('modeldata', $model->_data); $this->assignRef('params', $params); $this->assign('tipLocation', $params->get('tiplocation')); FabrikHelperHTML::debug($this->groups, 'form:view:groups'); // Cck in admin? $this->cck(); JDEBUG ? $profiler->mark('form view: after cck') : null; // Force front end templates $this->_basePath = COM_FABRIK_FRONTEND . '/views'; $this->_addJavascript($listModel->getId()); JDEBUG ? $profiler->mark('form view: after add js') : null; $this->_loadTmplBottom($form); JDEBUG ? $profiler->mark('form view: after tmpl bottom loaded') : null; if ($model->isEditable()) { $form->startTag = '<form action="' . $form->action . '" class="fabrikForm" method="post" name="' . $form->name . '" id="' . $form->formid . '" enctype="' . $model->getFormEncType() . '">'; $form->endTag = '</form>'; $form->fieldsetTag = 'fieldset'; $form->legendTag = 'legend'; } else { $form->startTag = '<div class="fabrikForm fabrikDetails" id="' . $form->formid . '">'; $form->endTag = '</div>'; $form->fieldsetTag = 'div'; $form->legendTag = 'h3'; } $this->assignRef('form', $form); JDEBUG ? $profiler->mark('form view: form assigned as ref') : null; $list = new stdClass(); $list->id = $form->record_in_database ? $model->getListModel()->getTable()->id : 0; $this->assignRef('list', $list); JDEBUG ? $profiler->mark('form view: before getRelatedTables()') : null; $this->linkedTables = $this->get('RelatedTables'); JDEBUG ? $profiler->mark('form view: after getRelatedTables()') : null; $this->setMessage(); $this->addTemplatePath($this->_basePath . '/' . $this->_name . '/tmpl/' . $tmpl); $root = $app->isAdmin() ? JPATH_ADMINISTRATOR : JPATH_SITE; $this->addTemplatePath($root . '/templates/' . $app->getTemplate() . '/html/com_fabrik/form/' . $tmpl); JDEBUG ? $profiler->mark('form view before template load') : null; }
/** * Create the sql query used to get the possible selectable value/labels used to create * the drop-down/checkboxes * * @param array $data data * @param bool $incWhere include where * @param array $opts query options * * @return mixed JDatabaseQuery or false if query can't be built */ protected function buildQuery($data = array(), $incWhere = true, $opts = array()) { $input = $this->app->input; $sig = isset($this->autocomplete_where) ? $this->autocomplete_where . '.' . $incWhere : $incWhere; $sig .= '.' . serialize($opts); $repeatCounter = FArrayHelper::getValue($opts, 'repeatCounter', 0); $db = FabrikWorker::getDbo(); if (isset($this->sql[$sig])) { return $this->sql[$sig]; } $params = $this->getParams(); $watch = $this->getWatchFullName(); $whereVal = null; $groups = $this->getFormModel()->getGroupsHiarachy(); $formModel = $this->getFormModel(); $watchElement = $this->getWatchElement(); // Test for ajax update if ($input->get('fabrik_cascade_ajax_update') == 1) { // Allow for multiple values - e.g. when observing a db join rendered as a checkbox $whereVal = $input->get('v', array(), 'array'); } else { if (isset($formModel->data) || isset($formModel->formData)) { $watchOpts = array('raw' => 1); if (isset($formModel->data)) { if ($watchElement->isJoin()) { $id = $watchElement->getFullName(true, false) . '_id'; $whereVal = FArrayHelper::getValue($formModel->data, $id); } else { $whereVal = $watchElement->getValue($formModel->data, $repeatCounter, $watchOpts); } } else { /* * If we're running onAfterProcess, formData will have short names in it, which means getValue() * won't find the watch element, as it's looking for full names. So if it exists, use formDataWithTableName. */ if (is_array($formModel->formDataWithTableName) && array_key_exists($watch, $formModel->formDataWithTableName)) { $whereVal = $watchElement->getValue($formModel->formDataWithTableName, $repeatCounter, $watchOpts); } else { $whereVal = $watchElement->getValue($formModel->formData, $repeatCounter, $watchOpts); } } // $$$ hugh - if not set, set to '' to avoid selecting entire table if (!isset($whereVal)) { $whereVal = ''; } } else { // $$$ hugh - probably rendering table view ... $watchRaw = $watch . '_raw'; if (isset($data[$watchRaw])) { $whereVal = $data[$watchRaw]; } else { // $$$ hugh ::sigh:: might be coming in via swapLabelsForvalues in pre_process phase // and join array in data will have been flattened. So try regular element name for watch. $noJoinWatchRaw = $watchElement->getFullName(true, false) . '_raw'; if (isset($data[$noJoinWatchRaw])) { $whereVal = $data[$noJoinWatchRaw]; } else { // $$$ hugh - if watched element has no value, we have been selecting all rows from CDD table // but should probably select none. // Unless its a cdd autocomplete list filter - seems sensible to populate that with the values matching the search term if ($this->app->input->get('method') !== 'autocomplete_options') { $whereVal = ''; } } } } } $where = ''; $whereKey = $params->get('cascadingdropdown_key'); if (!is_null($whereVal) && $whereKey != '') { $whereBits = strstr($whereKey, '___') ? explode('___', $whereKey) : explode('.', $whereKey); $whereKey = array_pop($whereBits); if (is_array($whereVal)) { foreach ($whereVal as &$v) { // Jaanus: Solving bug: imploded arrays when chbx in repeated group if (is_array($v)) { foreach ($v as &$vchild) { $vchild = FabrikString::safeQuote($vchild); } $v = implode(',', $v); } else { $v = FabrikString::safeQuote($v); } } // Jaanus: if count of where values is 0 or if there are no letters or numbers, only commas in imploded array $where .= count($whereVal) == 0 || !preg_match('/\\w/', implode(',', $whereVal)) ? '4 = -4' : $whereKey . ' IN ' . '(' . str_replace(',,', ',\'\',', implode(',', $whereVal)) . ')'; } else { $where .= $whereKey . ' = ' . $db->quote($whereVal); } } $filter = $params->get('cascadingdropdown_filter'); if (!empty($this->autocomplete_where)) { $where .= $where !== '' ? ' AND ' . $this->autocomplete_where : $this->autocomplete_where; } /* $$$ hugh - temporary hack to work around this issue: * http://fabrikar.com/forums/showthread.php?p=71288#post71288 * ... which is basically that if they are using {placeholders} in their * filter query, there's no point trying to apply that filter if we * aren't in form view, for instance when building a search filter * or in table view when the cdd is in a repeat group, 'cos there won't * be any {placeholder} data to use. * So ... for now, if the filter contains {...}, and view!=form ... skip it * $$$ testing fix for the bandaid, ccd JS should not be submitting data from form */ if (trim($filter) != '') { $where .= $where == '' ? ' ' : ' AND '; $where .= $filter; } $w = new FabrikWorker(); // $$$ hugh - add some useful stuff to search data $placeholders = is_null($whereVal) ? array() : array('whereval' => $whereVal, 'wherekey' => $whereKey); $join = $this->getJoin(); $where = $this->parseThisTable($where, $join); $data = array_merge($data, $placeholders); $where = $w->parseMessageForRepeats($where, $data, $this, $repeatCounter); $where = $w->parseMessageForPlaceHolder($where, $data); $table = $this->getDbName(); $key = $this->queryKey(); $orderBy = 'text'; $tables = $this->getFormModel()->getLinkedFabrikLists($params->get('join_db_name')); $listModel = JModelLegacy::getInstance('List', 'FabrikFEModel'); $val = $params->get('cascadingdropdown_label_concat'); if (!empty($val)) { $val = $this->parseThisTable($val, $join); $val = $w->parseMessageForPlaceHolder($val, $data); $val = 'CONCAT_WS(\'\', ' . $val . ')'; $orderBy = $val; } else { $val = FabrikString::safeColName($params->get($this->labelParam)); $val = preg_replace("#^`({$table})`\\.#", $db->qn($join->table_join_alias) . '.', $val); foreach ($tables as $tid) { $listModel->setId($tid); $listModel->getTable(); $formModel = $this->getFormModel(); $formModel->getGroupsHiarachy(); $orderBy = $val; // See if any of the tables elements match the db joins val/text foreach ($groups as $groupModel) { $elementModels = $groupModel->getPublishedElements(); foreach ($elementModels as $elementModel) { $element = $elementModel->element; if ($element->name == $val) { $val = $elementModel->modifyJoinQuery($val); } } } } } $val = str_replace($db->qn($table), $db->qn($join->table_join_alias), $val); $query = $db->getQuery(true); $query->select('DISTINCT(' . $key . ') AS value, ' . $val . 'AS text'); $desc = $params->get('cdd_desc_column', ''); if ($desc !== '') { $query->select(FabrikString::safeColName($desc) . ' AS description'); } $query->from($db->qn($table) . ' AS ' . $db->qn($join->table_join_alias)); $query = $this->buildQueryJoin($query); $where = FabrikString::rtrimword($where); if ($where !== '') { $query->where($where); } if (!JString::stristr($where, 'order by')) { $query->order($orderBy . ' ASC'); } $this->sql[$sig] = $query; FabrikHelperHTML::debug((string) $this->sql[$sig]); return $this->sql[$sig]; }
/** * $$$ rob 19/10/2011 now called before formatData() from getData() as otherwise element tips (created in element->renderListData()) * only contained first merged records data and not all merged records * * Collapses 'repeated joined' rows into a single row. * If a group is not repeating we just use the first row's data (as subsequent rows will contain the same data * Otherwise if the group is repeating we append each repeated record's data into the first row's data * All rows execpt the first row for each group are then unset (as unique subsequent row's data will be contained within * the first row) * @param array $data */ function formatForJoins(&$data) { $merge = $this->mergeJoinedData(); if (empty($merge)) { return; } $listid = $this->getTable()->id; $dbprimaryKey = FabrikString::safeColNameToArrayKey($this->getTable()->db_primary_key); $formModel = $this->getFormModel(); FabrikHelperHTML::debug($data, 'render:before formatForJoins'); $count = count($data); $last_pk = ''; $last_i = 0; $count = count($data); $can_repeats = array(); $can_repeats_tables = array(); $can_repeats_keys = array(); $can_repeats_pk_vals = array(); $remove = array(); // First, go round first row of data, and prep some stuff. // Basically, if doing a "reduce data" merge (merge == 2), we need to know what the // PK element is for each joined group (well, for each element, really) foreach ($data[0] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); // $$$ hugh - had to cache this stuff, because if you have a lot of rows and a lot of elements, // doing this many hundreds of times causes huge slowdown, exceeding max script execution time! // And we really only need to do it once for the first row. if (!isset($can_repeats[$tmpkey])) { $elementModel = $formModel->getElement($tmpkey); // $$$ rob - testing for linking join which is repeat but linked join which is not - still need separate info from linked to join //$can_repeats[$tmpkey] = $elementModel ? ($elementModel->getGroup()->canRepeat()) : 0; if ($merge == 2 && $elementModel) { if ($elementModel->getGroup()->canRepeat() || $elementModel->getGroup()->isJoin()) { // We need to work out the PK of the joined table. // So first, get the table name. $group = $elementModel->getGroup(); $join = $group->getJoinModel()->getJoin(); $join_table_name = $join->table_join; // We have the table name, so see if we already have it cached ... if (!isset($can_repeats_tables[$join_table_name])) { // We don't have it yet, so grab the PK $keys = $this->getPrimaryKeyAndExtra($join_table_name); if (!empty($keys) && array_key_exists('key', $keys[0])) { // OK, now we have the PK for the table $can_repeats_tables[$join_table_name] = $keys[0]; } } // Hopefully we now have the PK if (isset($can_repeats_tables[$join_table_name])) { $can_repeats_keys[$tmpkey] = $join_table_name . '___' . $can_repeats_tables[$join_table_name]['colname']; } // Create the array if it doesn't exist if (!isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]] = array(); } // Now store the if (!isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][0])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][0] = $data[0]->{$can_repeats_keys}[$tmpkey]; } } } $can_repeats[$tmpkey] = $elementModel ? $elementModel->getGroup()->canRepeat() || $elementModel->getGroup()->isJoin() : 0; } } for ($i = 0; $i < $count; $i++) { // $$$rob if rendering J article in PDF format __pk_val not in pdf table view //$next_pk = isset($data[$groupk][$i]->__pk_val) ? $data[$groupk][$i]->__pk_val : $data[$groupk][$i]->id; $next_pk = isset($data[$i]->__pk_val) ? $data[$i]->__pk_val : $data[$i]->{$dbprimaryKey}; if (!empty($last_pk) && $last_pk == $next_pk) { foreach ($data[$i] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); if (isset($data[$last_i]->{$key}) && $can_repeats[$tmpkey]) { if ($merge == 2 && !isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i] = $data[$i]->{$can_repeats_keys}[$tmpkey]; } // $$$ rob - what about data like yes/no where each viewable option needs to be shown? // $$$ rob - yeah commenting this out, not a good idea - as other cols for this record may have // different data so you end up with this col having 3 entries and the next col having four and you can't // see the correlation between the two sets of data. //if ($data[$groupk][$last_i]->$key != $val) { // $$$ rob meant that only one link to details was shown in admin - dont see the point in that //if (preg_match("#\W+fabrik___rowlink.*\W+listid=$listid\W#",$val)) { //continue; //} if ($origKey == $tmpkey) { // $$$ rob - this was just appending data with a <br> but as we do thie before the data is formatted // it was causing all sorts of issues for list rendering of links, dates etc. So now turn the data into // an array and at the end of this method loop over the data to encode the array into a json object. $do_merge = true; if ($merge == 2) { $pk_vals = array_count_values($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]]); if ($pk_vals[$data[$i]->{$can_repeats_keys}[$tmpkey]] > 1) { $do_merge = false; } } if ($do_merge) { // The raw data is not altererd at the moment - not sure that that seems correct but can't see any issues // with it currently $data[$last_i]->{$key} = (array) $data[$last_i]->{$key}; array_push($data[$last_i]->{$key}, $val); } } else { $json = $val; $data[$last_i]->{$origKey} = json_encode($json); } } } $remove[] = $i; continue; } else { if ($merge == 2) { foreach ($data[$i] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); if ($can_repeats[$tmpkey] && !isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i] = $data[$i]->{$can_repeats_keys}[$tmpkey]; } } } $last_i = $i; // $$$rob if rendering J article in PDF format __pk_val not in pdf table view $last_pk = $next_pk; } // $$$ rob ensure that we have a sequental set of keys otherwise ajax json will turn array into object $data = array_values($data); } for ($c = count($remove) - 1; $c >= 0; $c--) { unset($data[$remove[$c]]); } // $$$ rob loop over any data that was merged into an array and turn that into a json object foreach ($data as $gkey => $d) { foreach ($d as $k => $v) { if (is_array($v)) { foreach ($v as &$v2) { $v2 = FabrikWorker::JSONtoData($v2); } $v = json_encode($v); $data[$gkey]->{$k} = $v; } } } $data = array_values($data); }
/** * main setup routine for displaying the form/detail view * @param string template */ function display($tpl = null) { $profiler = JProfiler::getInstance('Application'); FabrikHelperHTML::framework(); $app = JFactory::getApplication(); $w = new FabrikWorker(); $config = JFactory::getConfig(); $model = $this->getModel('form'); $document = JFactory::getDocument(); $model->isMambot = $this->isMambot; $form = $model->getForm(); if ($model->render() === false) { return false; } $this->isMultiPage = $model->isMultiPage(); list($this->plugintop, $this->pluginbottom, $this->pluginend) = $this->get('FormPluginHTML'); $listModel = $model->getlistModel(); $table = $listModel->noTable() ? null : $listModel->getTable(); if (!$model->canPublish()) { if (!$app->isAdmin()) { echo JText::_('COM_FABRIK_FORM_NOT_PUBLISHED'); return false; } } $this->assign('rowid', $model->_rowId); $this->assign('access', $model->checkAccessFromListSettings()); if ($this->access == 0) { return JError::raiseWarning(500, JText::_('JERROR_ALERTNOAUTHOR')); } JDEBUG ? $profiler->mark('form view before join group ids got') : null; if (!$listModel->noTable()) { $joins = $listModel->getJoins(); $model->getJoinGroupIds($joins); } $params = $model->getParams(); $this->setTitle($w, $params); FabrikHelperHTML::debug($params->get('note'), 'note'); $params->def('icons', $app->getCfg('icons')); $params->set('popup', JRequest::getVar('tmpl') == 'component' ? 1 : 0); $this->editable = $model->_editable; $form->label = $this->get('label'); $form->intro = $this->get('Intro'); $form->action = $this->get('Action'); $form->formid = $model->_editable ? "form_" . $model->getId() : 'details_' . $model->getId(); $form->name = "form_" . $model->getId(); if ($form->error === '') { $form->error = JText::_('COM_FABRIK_FAILED_VALIDATION'); } //if errors made when submitting from a J plugin they are stored in the session $errors = $this->get('Errors'); $form->origerror = $form->error; $form->error = count($errors) > 0 ? $form->error : ''; $this->_addButtons(); JDEBUG ? $profiler->mark('form view before validation classes loaded') : null; $tmpl = $this->get('tmpl'); $this->assign('tmpl', $tmpl); JDEBUG ? $profiler->mark('form view before group view got') : null; $this->groups = $model->getGroupView($tmpl); JDEBUG ? $profiler->mark('form view after group view got') : null; $this->assignRef('data', $model->data); $this->assignRef('modeldata', $model->_data); $this->assignRef('params', $params); $this->assign('tipLocation', $params->get('tiplocation')); FabrikHelperHTML::debug($this->groups, 'form:view:groups'); //cck in admin? $this->cck(); JDEBUG ? $profiler->mark('form view: after cck') : null; //force front end templates $this->_basePath = COM_FABRIK_FRONTEND . DS . 'views'; $this->_addJavascript($listModel->getId()); JDEBUG ? $profiler->mark('form view: after add js') : null; $this->_loadTmplBottom($form); JDEBUG ? $profiler->mark('form view: after tmpl bottom loaded') : null; if ($model->_editable) { $form->startTag = '<form action="' . $form->action . '" class="fabrikForm" method="post" name="' . $form->name . '" id="' . $form->formid . '" enctype="' . $model->getFormEncType() . '">'; $form->endTag = '</form>'; } else { $form->startTag = '<div class="fabrikForm fabrikDetails" id="' . $form->formid . '">'; $form->endTag = '</div>'; } $form->endTag .= $this->pluginend; $this->assignRef('form', $form); JDEBUG ? $profiler->mark('form view: form assigned as ref') : null; $list = new stdClass(); $list->id = $form->record_in_database ? $model->getListModel()->getTable()->id : 0; $this->assignRef('list', $list); JDEBUG ? $profiler->mark('form view: before getRelatedTables()') : null; $this->assignRef('linkedTables', $this->get('RelatedTables')); JDEBUG ? $profiler->mark('form view: after getRelatedTables()') : null; $this->setMessage(); $this->addTemplatePath($this->_basePath . DS . $this->_name . DS . 'tmpl' . DS . $tmpl); $this->addTemplatePath(JPATH_SITE . DS . 'templates' . DS . $app->getTemplate() . DS . 'html' . DS . 'com_fabrik' . DS . 'form' . DS . $tmpl); JDEBUG ? $profiler->mark('form view before template load') : null; $text = $this->loadTemplate(); if ($params->get('process-jplugins') == 1 || $params->get('process-jplugins') == 2 && $model->_editable === false) { $opt = JRequest::getVar('option'); JRequest::setVar('option', 'com_content'); jimport('joomla.html.html.content'); $text .= '{emailcloak=off}'; $text = JHTML::_('content.prepare', $text); $text = preg_replace('/\\{emailcloak\\=off\\}/', '', $text); JRequest::setVar('option', $opt); } JDEBUG ? $profiler->mark('form view display end') : null; // allows you to use {placeholders} in form template. $text = $w->parseMessageForPlaceHolder($text, $model->_data); echo $text; }
/** * Get the map icons * * @return array */ public function getJSIcons() { $app = JFactory::getApplication(); $input = $app->input; $icons = array(); $w = new FabrikWorker(); $uri = JURI::getInstance(); $params = $this->getParams(); $templates = (array) $params->get('fb_gm_detailtemplate'); $templates_nl2br = (array) $params->get('fb_gm_detailtemplate_nl2br'); $listids = (array) $params->get('googlemap_table'); // Images for file system $aIconImgs = (array) $params->get('fb_gm_iconimage'); // Image from marker data $markerImages = (array) $params->get('fb_gm_iconimage2'); // Specified letter $letters = (array) $params->get('fb_gm_icon_letter'); $aFirstIcons = (array) $params->get('fb_gm_first_iconimage'); $aLastIcons = (array) $params->get('fb_gm_last_iconimage'); $titleElements = (array) $params->get('fb_gm_title_element'); $radiusElements = (array) $params->get('fb_gm_radius_element'); $radiusDefaults = (array) $params->get('fb_gm_radius_default'); $radiusUnits = (array) $params->get('fb_gm_radius_unit'); $groupClass = (array) $params->get('fb_gm_group_class'); $c = 0; $this->recordCount = 0; $maxMarkers = $params->get('fb_gm_markermax', 0); $recLimit = count($listids) == 1 ? $maxMarkers : 0; $limitMessageShown = false; $limitMessage = $params->get('fb_gm_markermax_message'); $groupedIcons = array(); $lc = 0; foreach ($listids as $listid) { $listModel = $this->getlistModel($listid); $template = JArrayHelper::getValue($templates, $c, ''); /** * One day we should get smarter about how we decide which elements to render * but for now all we can do is set formatAll(), in case they use an element * which isn't set for list display, which then wouldn't get rendered unless we do this. */ if (FabrikString::usesElementPlaceholders($template)) { $listModel->formatAll(true); } $template_nl2br = JArrayHelper::getValue($templates_nl2br, $c, '1') == '1'; $table = $listModel->getTable(); $mapsElements = FabrikHelperList::getElements($listModel, array('plugin' => 'googlemap', 'published' => 1)); $coordColumn = $mapsElements[0]->getFullName(true, false) . "_raw"; // Are we using random start location for icons? $listModel->_randomRecords = $params->get('fb_gm_random_marker') == 1 && $recLimit != 0 ? true : false; // Used in list model setLimits $input->set('limit' . $listid, $recLimit); $listModel->setLimits(); $nav = $listModel->getPagination(0, 0, $recLimit); $data = $listModel->getData(); $this->txt = array(); $k = 0; foreach ($data as $groupKey => $group) { foreach ($group as $row) { $customimagefound = false; $iconImg = JArrayHelper::getValue($aIconImgs, $c, ''); if ($k == 0) { $firstIcon = JArrayHelper::getValue($aFirstIcons, $c, $iconImg); if ($firstIcon !== '') { $iconImg = $firstIcon; } } $v = $this->getCordsFromData($row->{$coordColumn}); if ($v == array(0, 0)) { // Don't show icons with no data continue; } $rowdata = JArrayHelper::fromObject($row); $rowdata['rowid'] = $rowdata['__pk_val']; $html = $w->parseMessageForPlaceHolder($template, $rowdata); $titleElement = JArrayHelper::getValue($titleElements, $c, ''); $title = $titleElement == '' ? '' : strip_tags($row->{$titleElement}); /* $$$ hugh - if they provided a template, lets assume they will handle the link themselves. * http://fabrikar.com/forums/showthread.php?p=41550#post41550 * $$$ hugh - at some point the fabrik_view / fabrik_edit links became optional */ if (empty($html) && (array_key_exists('fabrik_view', $rowdata) || array_key_exists('fabrik_edit', $rowdata))) { // Don't insert line break in empty bubble without links $html .= "<br />"; // Use edit link by preference if (array_key_exists('fabrik_edit', $rowdata)) { if ($rowdata['fabrik_edit'] != '') { $html .= "<br />"; } $html .= $rowdata['fabrik_edit']; } else { if ($rowdata['fabrik_view'] != '') { $html .= "<br />"; } $html .= $rowdata['fabrik_view']; } } if ($template_nl2br) { /* * $$$ hugh - not sure why we were doing this rather than nl2br? If there was a reason, this is still broken, as it ends up inserting two breaks. So if we can't use nl2br ... I need fix this before using it again! $html = str_replace(array("\n\r"), "<br />", $html); $html = str_replace(array("\r\n"), "<br />", $html); $html = str_replace(array("\n", "\r"), "<br />", $html); */ $html = nl2br($html); } $html = str_replace("'", '"', $html); $this->txt[] = $html; if ($iconImg == '') { $iconImg = JArrayHelper::getValue($markerImages, $c, ''); if ($iconImg != '') { $iconImg = JArrayHelper::getValue($rowdata, $iconImg, ''); // Get the src preg_match('/src=["|\'](.*?)["|\']/', $iconImg, $matches); if (array_key_exists(1, $matches)) { $iconImg = $matches[1]; // Check file exists $path = str_replace(COM_FABRIK_LIVESITE, '', $iconImg); if (JFile::exists(JPATH_BASE . $path)) { $customimagefound = true; } } } if ($iconImg != '') { list($width, $height) = $this->markerSize($iconImg); } else { // Standard google map icon size $width = 20; $height = 34; } } else { // Standard google map icon size list($width, $height) = $this->markerSize(JPATH_SITE . '/images/stories/' . $iconImg); } $gClass = JArrayHelper::getValue($groupClass, 0, ''); if (!empty($gClass)) { $gClass .= '_raw'; $gClass = isset($row->{$gClass}) ? $row->{$gClass} : ''; } if (array_key_exists($v[0] . $v[1], $icons)) { $existingIcon = $icons[$v[0] . $v[1]]; if ($existingIcon['groupkey'] == $groupKey) { /* $$$ hugh - this inserts label between multiple record $html, but not at the top. * If they want to insert label, they can do it themselves in the template. * $icons[$v[0].$v[1]][2] = $icons[$v[0].$v[1]][2] . "<h6>$table->label</h6>" . $html; * Don't insert linebreaks in empty bubble */ if ($html != '') { $html = "<br />" . $html; } $icons[$v[0] . $v[1]][2] = $icons[$v[0] . $v[1]][2] . $html; if ($customimagefound) { $icons[$v[0] . $v[1]][3] = $iconImg; } } else { $groupedIcons[] = array($v[0], $v[1], $html, $iconImg, $width, $height, 'groupkey' => $groupKey, 'listid' => $listid, 'title' => $title, 'groupClass' => 'type' . $gClass); } } else { // Default icon - lets see if we need to use a letter icon instead if (JArrayHelper::getValue($letters, $c, '') != '') { $iconImg = $uri->getScheme() . '://www.google.com/mapfiles/marker' . JString::strtoupper($letters[$c]) . '.png'; } $icons[$v[0] . $v[1]] = array($v[0], $v[1], $html, $iconImg, $width, $height, 'groupkey' => $groupKey, 'listid' => $listid, 'title' => $title, 'groupClass' => 'type' . $gClass); } if ($params->get('fb_gm_use_radius', '0') == '1') { $radiusElement = JArrayHelper::getValue($radiusElements, $c, ''); $radiusUnits = JArrayHelper::getValue($radiusUnits, $c, 'k'); $radiusMeters = $radiusUnits == 'k' ? 1000 : 1609.34; if (!empty($radiusElement)) { $radius = (double) $row->{$radiusElement}; $radius *= $radiusMeters; $icons[$v[0] . $v[1]]['radius'] = $radius; } else { $default = (double) JArrayHelper::getvalue($radiusDefaults, $c, 50); $default *= $radiusMeters; $icons[$v[0] . $v[1]]['radius'] = $default; } } $icons[$v[0] . $v[1]]['c'] = $c; $this->recordCount++; $k++; } } // Replace last icon? $iconImg = JArrayHelper::getValue($aLastIcons, $c, ''); if ($iconImg != '') { list($width, $height) = $this->markerSize(JPATH_SITE . '/media/com_fabrik/images/' . $iconImg); $icons[$v[0] . $v[1]][3] = $iconImg; $icons[$v[0] . $v[1]][4] = $width; $icons[$v[0] . $v[1]][5] = $height; } $c++; } // Replace coord keys with numeric keys $icons = array_values($icons); $icons = array_merge($icons, $groupedIcons); if ($maxMarkers != 0 && $maxMarkers < count($icons)) { $icons = array_slice($icons, -$maxMarkers); } $limitMessageShown = !($k >= $recLimit); if (!$limitMessageShown && $recLimit !== 0 && $limitMessage != '') { $app->enqueueMessage($limitMessage); } FabrikHelperHTML::debug($icons, 'map'); return $icons; }
/** * $$$ rob 19/10/2011 now called before formatData() from getData() as otherwise element tips (created in element->renderListData()) * only contained first merged records data and not all merged records * * Collapses 'repeated joined' rows into a single row. * If a group is not repeating we just use the first row's data (as subsequent rows will contain the same data * Otherwise if the group is repeating we append each repeated record's data into the first row's data * All rows execpt the first row for each group are then unset (as unique subsequent row's data will be contained within * the first row) * @param array $data */ function formatForJoins(&$data) { $merge = $this->mergeJoinedData(); if (empty($merge)) { return; } $listid = $this->getTable()->id; $dbprimaryKey = FabrikString::safeColNameToArrayKey($this->getTable()->db_primary_key); $formModel = $this->getFormModel(); FabrikHelperHTML::debug($data, 'render:before formatForJoins'); $count = count($data); $last_pk = ''; $last_i = 0; $count = count($data); $can_repeats = array(); $remove = array(); for ($i = 0; $i < $count; $i++) { // $$$rob if rendering J article in PDF format __pk_val not in pdf table view //$next_pk = isset($data[$groupk][$i]->__pk_val) ? $data[$groupk][$i]->__pk_val : $data[$groupk][$i]->id; $next_pk = isset($data[$i]->__pk_val) ? $data[$i]->__pk_val : $data[$i]->{$dbprimaryKey}; if (!empty($last_pk) && $last_pk == $next_pk) { foreach ($data[$i] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); // $$$ hugh - had to cache this stuff, because if you have a lot of rows and a lot of elements, // doing this many hundreds of times causes huge slowdown, exceeding max script execution time! // And we really only need to do it once for the first row. if (!isset($can_repeats[$tmpkey])) { $elementModel = $formModel->getElement($tmpkey); // $$$ rob - testing for linking join which is repeat but linked join which is not - still need separate info from linked to join //$can_repeats[$tmpkey] = $elementModel ? ($elementModel->getGroup()->canRepeat()) : 0; $can_repeats[$tmpkey] = $elementModel ? $elementModel->getGroup()->canRepeat() || $elementModel->getGroup()->isJoin() : 0; //$can_repeats[$tmpkey] = 0; } if (isset($data[$last_i]->{$key}) && $can_repeats[$tmpkey]) { // $$$ rob - what about data like yes/no where each viewable option needs to be shown? // $$$ rob - yeah commenting this out, not a good idea - as other cols for this record may have // different data so you end up with this col having 3 entries and the next col having four and you can't // see the correlation between the two sets of data. //if ($data[$groupk][$last_i]->$key != $val) { // $$$ rob meant that only one link to details was shown in admin - dont see the point in that //if (preg_match("#\W+fabrik___rowlink.*\W+listid=$listid\W#",$val)) { //continue; //} if ($origKey == $tmpkey) { // $$$ rob - this was just appending data with a <br> but as we do thie before the data is formatted // it was causing all sorts of issues for list rendering of links, dates etc. So now turn the data into // an array and at the end of this method loop over the data to encode the array into a json object. // The raw data is not altererd at the moment - not sure that that seems correct but can't see any issues // with it currently $data[$last_i]->{$key} = (array) $data[$last_i]->{$key}; array_push($data[$last_i]->{$key}, $val); } else { $json = $val; $data[$last_i]->{$origKey} = json_encode($json); } } } $remove[] = $i; continue; } else { $last_i = $i; // $$$rob if rendering J article in PDF format __pk_val not in pdf table view $last_pk = $next_pk; } // $$$ rob ensure that we have a sequental set of keys otherwise ajax json will turn array into object $data = array_values($data); } for ($c = count($remove) - 1; $c >= 0; $c--) { unset($data[$remove[$c]]); } // $$$ rob loop over any data that was merged into an array and turn that into a json object foreach ($data as $gkey => $d) { foreach ($d as $k => $v) { if (is_array($v)) { foreach ($v as &$v2) { $v2 = FabrikWorker::JSONtoData($v2); } $v = json_encode($v); $data[$gkey]->{$k} = $v; } } } $data = array_values($data); }
/** * Overwrite session and search all filters with posted data * * @param array &$filters filter array * * @return void */ private function getPostFilters(&$filters) { $input = $this->app->input; //$item = $this->listModel->getTable(); $request = $this->getPostFilterArray(); $elements = $this->listModel->getElements('id'); $filterKeys = array_keys($filters); $values = FArrayHelper::getValue($request, 'value', array()); $searchTypes = FArrayHelper::getValue($filters, 'search_type', array()); $conditions = FArrayHelper::getValue($request, 'condition', array()); $usedMerges = array(); FabrikHelperHTML::debug($filters, 'filter array: start getPostFilters'); if (!empty($request) && array_key_exists('key', $request)) { $keyInts = array_keys($request['key']); $ajaxPost = JString::strtolower($input->server->get('HTTP_X_REQUESTED_WITH')); $this->listModel->ajaxPost = $ajaxPost; $this->listModel->postValues = $values; foreach ($keyInts as $i) { $value = FArrayHelper::getValue($values, $i, ''); $key = FArrayHelper::getValue($request['key'], $i); $elid = FArrayHelper::getValue($request['elementid'], $i); $condition = FArrayHelper::getValue($conditions, $i); if ($key == '') { continue; } // Index is the filter index for a previous filter that uses the same element id if (!in_array($elid, $usedMerges)) { $index = array_key_exists('elementid', $filters) ? array_search($elid, (array) $filters['elementid']) : false; } else { $index = false; } if ($index !== false) { $usedMerges[] = $elid; } /** * $$$rob empty post filters SHOULD overwrite previous filters, as the user has submitted * this filter with nothing selected */ /*if (is_string($value) && trim($value) == '') { continue; } */ // $$$ rob set a var for empty value - regardless of whether its an array or string $emptyValue = (is_string($value) && trim($value) == '' || is_array($value) && trim(implode('', $value)) == '') && $condition !== 'EMPTY'; /** * $$rob ok the above meant that require filters stopped working as soon as you submitted * an empty search! * So now add in the empty search IF there is NOT a previous filter in the search data */ if ($emptyValue && $index === false) { continue; } /** * $$$ rob if we are posting an empty value then we really have to clear the filter out from the * session. Otherwise the filter is run as "where field = ''" */ if ($emptyValue && $index !== false) { /* * Testing clearing only if normal filter, previous test on searchType != 'searchall' * meant advanced search filters were removed on page nav */ if (FArrayHelper::getValue($searchTypes, $index) == 'normal') { $this->clearAFilter($filters, $index); } // $$$ rob - regardless of whether the filter was added by search all or not - don't overwrite it with post filter continue; } $origCondition = $condition; $filters['orig_condition'][] = $condition; if ($condition === 'EMPTY') { $condition = '='; $value = ''; } $elementModel = $elements[$elid]; if (!is_a($elementModel, 'PlgFabrik_Element')) { continue; } // Date element's have specific empty values if ($origCondition === 'EMPTY') { $value = $elementModel->emptyFilterValue(); } // If the request key is already in the filter array - unset it if ($index !== false) { foreach ($filterKeys as $fKey) { if (is_array($filters[$fKey]) && array_key_exists($index, $filters[$fKey])) { // Don't unset search all filters when the value is empty and continue so we don't add in a new filter if (FArrayHelper::getValue($searchTypes, $index) == 'searchall' && $value == '') { continue 2; } // $$$rob we DO need to unset unset($filters[$fKey][$index]); } } } if (is_array($value)) { // Ensure the array is indexed starting at 0. $value = array_values($value); // Empty ranged data test if (FArrayHelper::getValue($value, 0) == '' && FArrayHelper::getValue($value, 1) == '') { continue; } } $eval = is_array($value) ? FArrayHelper::getValue($value, 'eval', FABRIKFILTER_TEXT) : FABRIKFILTER_TEXT; if (!is_a($elementModel, 'PlgFabrik_ElementDatabasejoin')) { $fieldDesc = $elementModel->getFieldDescription(); if (JString::stristr($fieldDesc, 'INT')) { if (is_numeric($value) && $request['condition'][$i] == '=') { $eval = FABRKFILTER_NOQUOTES; } } } /** * $$$ rob - search all and dropdown filter: Search first on searchall = usa, then select dropdown to usa. * post filter query overwrites search all query, but uses add so = where id REGEX 'USA' AND country LIKE '%USA' * this code swaps the first */ $joinMode = JString::strtolower($request['join'][$i]) != 'where' ? $request['join'][$i] : 'AND'; if (!empty($filters)) { if ($i == 0) { $joinModes = FArrayHelper::getValue($filters, 'join', array('AND')); $joinMode = array_pop($joinModes); // $$$ rob - If search all made, then the post filters should filter further the results $tmpSearchTypes = FArrayHelper::getValue($filters, 'search_type', array('normal')); $lastSearchType = array_pop($tmpSearchTypes); if ($lastSearchType == 'searchall') { $joinMode = 'AND'; } } } // Add request filter to end of filter array $element = $elementModel->getElement(); $elParams = $elementModel->getParams(); $filters['value'][] = $value; $filters['condition'][] = urldecode($condition); $filters['join'][] = $joinMode; $filters['no-filter-setup'][] = $element->filter_type == '' ? 1 : 0; $filters['hidden'][] = $element->filter_type == '' ? 1 : 0; /* * $$$ hugh - need to check for magic quotes, otherwise filter keys for * CONCAT's get munged into things like CONCAT(last_name,\', \',first_name) * which then blows up the WHERE query. */ if (get_magic_quotes_gpc()) { $filters['key'][] = stripslashes(urldecode($key)); } else { $filters['key'][] = urldecode($key); } $filters['search_type'][] = FArrayHelper::getValue($request['search_type'], $i, 'normal'); $filters['match'][] = $element->filter_exact_match; $filters['full_words_only'][] = $elParams->get('full_words_only'); $filters['eval'][] = $eval; $filters['required'][] = $elParams->get('filter_required'); $filters['access'][] = $elParams->get('filter_access'); $filters['grouped_to_previous'][] = FArrayHelper::getValue($request['grouped_to_previous'], $i, '0'); $filters['label'][] = $elementModel->getListHeading(); $filters['elementid'][] = $elid; $filters['raw'][] = false; } } $this->listModel->tmpFilters = $filters; FabrikHelperHTML::debug($filters, 'filter array: before onGetPostFilter'); FabrikWorker::getPluginManager()->runPlugins('onGetPostFilter', $this->listModel, 'list', $filters); FabrikHelperHTML::debug($filters, 'filter array: after onGetPostFilter'); $filters = $this->listModel->tmpFilters; }
/** * get a single column of data from the table, test for element filters * @param string column to get * @return array values for the column - empty array if no results found */ function getColumnData($col) { $table =& $this->getTable(); $fbConfig =& JComponentHelper::getParams('com_fabrik'); $db = $this->getDb(); $el = $this->getFormModel()->getElement($col); $col = FabrikString::safeColName($col); $el->encryptFieldName($col); $tablename = $table->db_table_name; $tablename = FabrikString::safeColName($tablename); $query = "SELECT DISTINCT({$col}) FROM " . $tablename . ' ' . $this->_buildQueryJoin(); $query .= $this->_buildQueryWhere(false); $query .= " LIMIT " . $fbConfig->get('filter_list_max', 100); $query = $this->pluginQuery($query); $db->setQuery($query); $res = $db->loadResultArray(); if ((int) $fbConfig->get('filter_list_max', 100) == count($res)) { JError::raiseNotice(500, JText::sprintf('COM_FABRIK_FILTER_LIST_MAX_REACHED', $col)); } FabrikHelperHTML::debug($query, 'filter:getColumnData query'); if (is_null($res)) { $res = array(); } return $res; }
/** * $$$ rob 19/10/2011 now called before formatData() from getData() as otherwise element tips (created in element->renderListData()) * only contained first merged records data and not all merged records * * Collapses 'repeated joined' rows into a single row. * If a group is not repeating we just use the first row's data (as subsequent rows will contain the same data * Otherwise if the group is repeating we append each repeated record's data into the first row's data * All rows execpt the first row for each group are then unset (as unique subsequent row's data will be contained within * the first row) * * @param array &$data list data * * @return void */ protected function formatForJoins(&$data) { $merge = $this->mergeJoinedData(); if (empty($merge)) { return; } $listid = $this->getTable()->id; $dbprimaryKey = FabrikString::safeColNameToArrayKey($this->getTable()->db_primary_key); $formModel = $this->getFormModel(); $db = $this->getDb(); FabrikHelperHTML::debug($data, 'render:before formatForJoins'); $count = count($data); $last_pk = ''; $last_i = 0; $count = count($data); $can_repeats = array(); $can_repeats_tables = array(); $can_repeats_keys = array(); $can_repeats_pk_vals = array(); $remove = array(); if (empty($data)) { return; } /* First, go round first row of data, and prep some stuff. * Basically, if doing a "reduce data" merge (merge == 2), we need to know what the * PK element is for each joined group (well, for each element, really) */ foreach ($data[0] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); /* $$$ hugh - had to cache this stuff, because if you have a lot of rows and a lot of elements, * doing this many hundreds of times causes huge slowdown, exceeding max script execution time! * And we really only need to do it once for the first row. */ if (!isset($can_repeats[$tmpkey])) { $elementModel = $formModel->getElement($tmpkey); // $$$ rob - testing for linking join which is repeat but linked join which is not - still need separate info from linked to join // $can_repeats[$tmpkey] = $elementModel ? ($elementModel->getGroup()->canRepeat()) : 0; if ($merge == 2 && $elementModel) { if ($elementModel->getGroup()->canRepeat() || $elementModel->getGroup()->isJoin()) { // We need to work out the PK of the joined table. // So first, get the table name. $group = $elementModel->getGroup(); $join = $group->getJoinModel()->getJoin(); $join_table_name = $join->table_join; // We have the table name, so see if we already have it cached ... if (!isset($can_repeats_tables[$join_table_name])) { // We don't have it yet, so grab the PK $keys = $this->getPrimaryKeyAndExtra($join_table_name); if (!empty($keys) && array_key_exists('key', $keys[0])) { // OK, now we have the PK for the table $can_repeats_tables[$join_table_name] = $keys[0]; } else { // $$$ hugh - might be a view, so Hail Mary attempt to get PK $query = $db->getQuery(true); $query->select('db_primary_key')->from('#__{package}_lists')->where('db_table_name = ' . $db->quote($join_table_name)); $db->setQuery($query); $join_pk = $db->loadResult(); if (!empty($join_pk)) { $can_repeats_tables[$join_table_name] = array('colname' => FabrikString::shortColName($join_pk)); } } } // Hopefully we now have the PK if (isset($can_repeats_tables[$join_table_name])) { $can_repeats_keys[$tmpkey] = $join_table_name . '___' . $can_repeats_tables[$join_table_name]['colname']; } // Create the array if it doesn't exist if (!isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]] = array(); } // Now store the if (!isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][0])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][0] = $data[0]->{$can_repeats_keys}[$tmpkey]; } } } $can_repeats[$tmpkey] = $elementModel ? $elementModel->getGroup()->canRepeat() || $elementModel->getGroup()->isJoin() : 0; } } for ($i = 0; $i < $count; $i++) { // $$$rob if rendering J article in PDF format __pk_val not in pdf table view $next_pk = isset($data[$i]->__pk_val) ? $data[$i]->__pk_val : $data[$i]->{$dbprimaryKey}; if (!empty($last_pk) && $last_pk == $next_pk) { foreach ($data[$i] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); if ($can_repeats[$tmpkey]) { if ($merge == 2 && !isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i] = $data[$i]->{$can_repeats_keys}[$tmpkey]; } if ($origKey == $tmpkey) { /* $$$ rob - this was just appending data with a <br> but as we do thie before the data is formatted * it was causing all sorts of issues for list rendering of links, dates etc. So now turn the data into * an array and at the end of this method loop over the data to encode the array into a json object. */ $do_merge = true; if ($merge == 2) { $pk_vals = array_count_values(array_filter($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]])); if ($data[$i]->{$can_repeats_keys}[$tmpkey] != '') { if ($pk_vals[$data[$i]->{$can_repeats_keys}[$tmpkey]] > 1) { $do_merge = false; } } } if ($do_merge) { /* The raw data is not altererd at the moment - not sure that that seems correct but can't see any issues * with it currently * $$$ hugh - added processing of raw data, needed for _raw placeholders * in things like custom links */ $data[$last_i]->{$key} = (array) $data[$last_i]->{$key}; array_push($data[$last_i]->{$key}, $val); $rawkey = $key . '_raw'; $rawval = $data[$i]->{$rawkey}; $data[$last_i]->{$rawkey} = (array) $data[$last_i]->{$rawkey}; array_push($data[$last_i]->{$rawkey}, $rawval); } } else { /* $$$ hugh - don't think we need this, now we're processing _raw data? if (!is_array($data[$last_i]->$origKey)) { $json= $val; $data[$last_i]->$origKey = json_encode($json); } */ } } } $remove[] = $i; continue; } else { if ($merge == 2) { foreach ($data[$i] as $key => $val) { $origKey = $key; $tmpkey = FabrikString::rtrimword($key, '_raw'); if ($can_repeats[$tmpkey] && !isset($can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i])) { $can_repeats_pk_vals[$can_repeats_keys[$tmpkey]][$i] = $data[$i]->{$can_repeats_keys}[$tmpkey]; } } } $last_i = $i; // $$$rob if rendering J article in PDF format __pk_val not in pdf table view $last_pk = $next_pk; } // $$$ rob ensure that we have a sequental set of keys otherwise ajax json will turn array into object $data = array_values($data); } for ($c = count($remove) - 1; $c >= 0; $c--) { unset($data[$remove[$c]]); } // $$$ rob loop over any data that was merged into an array and turn that into a json object foreach ($data as $gkey => $d) { foreach ($d as $k => $v) { if (is_array($v)) { foreach ($v as &$v2) { $v2 = FabrikWorker::JSONtoData($v2); } $v = json_encode($v); $data[$gkey]->{$k} = $v; } } } $data = array_values($data); }
/** * create the sql query used to get the join data * @param array * @return string */ function _buildQuery($data = array(), $repeatCounter = 0) { $db = JFactory::getDBO(); if (!isset($this->_sql)) { $this->_sql = array(); } if (array_key_exists($repeatCounter, $this->_sql)) { return $this->_sql[$repeatCounter]; } $params =& $this->getParams(); $element =& $this->getElement(); $watch = $this->_getWatchFullName(); $whereval = null; $groups =& $this->getForm()->getGroupsHiarachy(); foreach ($groups as $groupModel) { $elementModels =& $groupModel->getPublishedElements(); foreach ($elementModels as $elementModel) { $fullName = $elementModel->getFullName(true, true, true); if ($fullName == $watch) { //test for ajax update if (JRequest::getVar('fabrik_cascade_ajax_update') == 1) { $whereval = JRequest::getVar('v'); } else { if (isset($this->_form->_data)) { $whereval = $elementModel->getValue($this->_form->_data, $repeatCounter); // $$$ hugh - temporary bandaid to fix 'array' issue in view=details // @TODO fix underlying cause in database join getValue // http://fabrikar.com/forums/showthread.php?p=63512#post63512 if (is_array($whereval)) { $whereval = $whereval[0]; } elseif (!isset($whereval)) { $whereval = ''; } } else { // $$$ hugh - prolly rendering table view ... $watch_raw = $watch . '_raw'; if (isset($data[$watch_raw])) { $whereval = $data[$watch_raw]; } else { // $$$ hugh ::sigh:: might be coming in via swapLabelsForvalues in pre_process phase // and join array in data will have been flattened. So try regular element name for watch. $no_join_watch_raw = $elementModel->getFullName(false, true, false) . "_raw"; if (isset($data[$no_join_watch_raw])) { $whereval = $data[$no_join_watch_raw]; } else { // $$$ hugh - if watched element has no value, we have been selecting all rows from CDD table // but should probably select none. $whereval = ''; } } } } continue 2; } } } $where = ''; $wherekey = $params->get('cascadingdropdown_key'); if (!is_null($whereval) && $wherekey != '') { $wherekey = array_pop(explode('___', $wherekey)); $where = " WHERE {$wherekey} = " . $db->Quote($whereval); } $filter = $params->get('cascadingdropdown_filter'); $wherewhen = $params->get('cascadingdropdown_where_when', '3'); $isnew = JRequest::getInt('rowid', 0) === 0; if ($isnew && $wherewhen == '2') { $filter = ''; } else { if (!$isnew && $wherewhen == '1') { $filter = ''; } } // $$$ hugh - temporary hack to work around this issue: // http://fabrikar.com/forums/showthread.php?p=71288#post71288 // ... which is basically that if they are using {placeholders} in their // filter query, there's no point trying to apply that filter if we // aren't in form view, for instance when building a search filter // or in table view when the cdd is in a repeat group, 'cos there won't // be any {placeholder} data to use. // So ... for now, if the filter contains {...}, and view!=form ... skip it // $$$ testing fix for the bandaid, ccd JS should not be submitting data from form if (trim($filter) != '') { //$this_view = JRequest::getVar('view', ''); //if ($this_view =='form' || ($this_view != 'form' && !preg_match('#\{.+\}#', $filter))) { $where .= $where == '' ? ' WHERE ' : ' AND '; $where .= $filter; //} } $w = new FabrikWorker(); // $$$ hugh - add some useful stuff to search data if (!is_null($whereval)) { $placeholders = array('whereval' => $whereval, 'wherekey' => $wherekey); } else { $placeholders = array(); } $join =& $this->getJoin(); $where = str_replace("{thistable}", $join->table_join_alias, $where); if (!empty($this->_autocomplete_where)) { $where .= stristr($where, 'WHERE') ? " AND " . $this->_autocomplete_where : ' WHERE ' . $this->_autocomplete_where; } $data = array_merge($data, $placeholders); $where = $w->parseMessageForPlaceHolder($where, $data); $table = $this->getDbName(); $key = FabrikString::safeColName($params->get('cascadingdropdown_id')); $key = str_replace("`{$table}`", "`{$join->table_join_alias}`", $key); $orderby = 'text'; $tables =& $this->getForm()->getLinkedFabrikTables($params->get('join_db_name')); $tableModel =& JModel::getInstance('Table', 'FabrikModel'); $val = $params->get('cascadingdropdown_label_concat'); if (!empty($val)) { $val = str_replace("{thistable}", $join->table_join_alias, $val); $val = $w->parseMessageForPlaceHolder($val, $data); $val = "CONCAT({$val})"; $orderby = $val; } else { $val = FabrikString::safeColName($params->get('cascadingdropdown_label')); $val = preg_replace("#^`({$table})`\\.#", "`{$join->table_join_alias}`.", $val); foreach ($tables as $tid) { $tableModel->setId($tid); $tableModel->getTable(); $formModel =& $tableModel->getForm(); $formModel->getGroupsHiarachy(); $orderby = $val; //see if any of the tables elements match the db joins val/text foreach ($groups as $groupModel) { $elementModels =& $groupModel->getPublishedElements(); foreach ($elementModels as $elementModel) { $element =& $elementModel->_element; if ($element->name == $val) { $val = $elementModel->modifyJoinQuery($val); } } } } } $val = str_replace("`{$table}`", "`{$join->table_join_alias}`", $val); // $$$ rob @todo commented query wont work when label/id selected from joined group of look up table // not sure if we should fix this or just remove those elements from the cdd element id/label fields //see http://fabrikar.com/forums/showthread.php?t=15546 //$this->_sql[$repeatCounter] = "SELECT DISTINCT($key) AS value, $val AS text FROM ".$db->nameQuote($table) .' AS '.$db->nameQuote($join->table_join_alias)." $where " . $tableModel->_buildQueryJoin() . " "; $sql = "SELECT DISTINCT({$key}) AS value, {$val} AS text"; $desc = $params->get('cdd_desc_column', ''); if ($desc !== '') { // $$$ hugh - need to do the table alias name swap thing! $desc = FabrikString::safeColName($desc); $desc = preg_replace("#^`({$table})`\\.#", "`{$join->table_join_alias}`.", $desc); $sql .= ", {$desc} AS description"; } $sql .= " FROM " . $db->nameQuote($table) . ' AS ' . $db->nameQuote($join->table_join_alias) . " {$where} "; $this->_sql[$repeatCounter] = $sql; if (!JString::stristr($where, 'order by')) { $this->_sql[$repeatCounter] .= " ORDER BY {$orderby} ASC "; } FabrikHelperHTML::debug($this->_sql[$repeatCounter]); return $this->_sql[$repeatCounter]; }
/** * main setup routine for displaying the form/detail view * @param string template */ function display($tpl = null) { global $_PROFILER; FabrikHelperHTML::framework(); $app = JFactory::getApplication(); $w = new FabrikWorker(); $config = JFactory::getConfig(); $model = $this->getModel('form'); $document = JFactory::getDocument(); FabrikHelperHTML::mootools(); $model->isMambot = $this->isMambot; $form = $model->getForm(); if ($model->render() === false) { return false; } $this->isMultiPage = $model->isMultiPage(); list($this->plugintop, $this->pluginbottom, $this->pluginend) = $model->_getFormPluginHTML(); $listModel = $model->getlistModel(); $table = $listModel->noTable() ? null : $listModel->getTable(); if (!$model->canPublish()) { if (!$app->isAdmin()) { echo JText::_('COM_FABRIK_FORM_NOT_PUBLISHED'); return false; } } $this->assign('access', $model->checkAccessFromListSettings()); if ($this->access == 0) { return JError::raiseWarning(500, JText::_('JERROR_ALERTNOAUTHOR')); } JDEBUG ? $_PROFILER->mark('form view before join group ids got') : null; if (!$listModel->noTable()) { $joins =& $listModel->getJoins(); $model->getJoinGroupIds($joins); } $params = $model->getParams(); $this->setTitle($w, $params); FabrikHelperHTML::debug($params->get('note'), 'note'); $params->def('icons', $app->getCfg('icons')); $params->set('popup', JRequest::getVar('tmpl') == 'component' ? 1 : 0); $this->editable = $model->_editable; $form->label = $this->get('label'); $form->intro = $this->get('Intro'); $form->action = $this->get('Action'); $form->formid = $model->_editable ? "form_" . $model->getId() : 'details_' . $model->getId(); $form->name = "form_" . $model->getId(); if ($form->error === '') { $form->error = JText::_('COM_FABRIK_FAILED_VALIDATION'); } $form->origerror = $form->error; $form->error = count($model->_arErrors) > 0 ? $form->error : ''; $this->_addButtons(); JDEBUG ? $_PROFILER->mark('form view before validation classes loaded') : null; $model->loadValidationRuleClasses(); $t = $model->_editable ? $form->form_template : $form->view_only_template; if ($this->isMambot) { // need to do this otherwise when viewing form in form module and in category/blog content page // you get a 500 error regarding layout default not found. $form->form_template = JRequest::getVar('flayout', $t); } else { $form->form_template = JRequest::getVar('layout', $t); } $tmpl = $this->get('tmpl'); $this->assign('tmpl', $tmpl); JDEBUG ? $_PROFILER->mark('form view before group view got') : null; $this->groups = $model->getGroupView($tmpl); //$this->assignRef('groups', $this->get('GroupView')); JDEBUG ? $_PROFILER->mark('form view after group view got') : null; $this->assignRef('data', $model->data); $this->assignRef('modeldata', $model->_data); $this->assignRef('params', $params); FabrikHelperHTML::debug($this->groups, 'form:view:groups'); //cck in admin? $this->cck(); JDEBUG ? $_PROFILER->mark('form view: after cck') : null; //force front end templates $this->_basePath = COM_FABRIK_FRONTEND . DS . 'views'; $this->_addJavascript($listModel->getId()); JDEBUG ? $_PROFILER->mark('form view: after add js') : null; $this->_loadTmplBottom($form); JDEBUG ? $_PROFILER->mark('form view: after tmpl bottom loaded') : null; if ($model->_editable) { $form->startTag = "<form action=\"{$form->action}\" class=\"fabrikForm\" method=\"post\" name=\"{$form->name}\" id=\"{$form->formid}\" enctype=\"{$model->getFormEncType()}\">"; $form->endTag = "</form>"; } else { $form->startTag = '<div class="fabrikForm fabrikDetails" id="' . $form->formid . '">'; $form->endTag = '</div>'; } $form->endTag .= $this->pluginend; $this->assignRef('form', $form); JDEBUG ? $_PROFILER->mark('form view: form assigned as ref') : null; $list = new stdClass(); $list->id = $form->record_in_database ? $model->getListModel()->getTable()->id : 0; $this->assignRef('list', $list); JDEBUG ? $_PROFILER->mark('form view: before getRelatedTables()') : null; $this->assignRef('linkedTables', $this->get('RelatedTables')); JDEBUG ? $_PROFILER->mark('form view: after getRelatedTables()') : null; $this->setMessage(); $this->addTemplatePath($this->_basePath . DS . $this->_name . DS . 'tmpl' . DS . $tmpl); $this->addTemplatePath(JPATH_SITE . DS . 'templates' . DS . $app->getTemplate() . DS . 'html' . DS . 'com_fabrik' . DS . 'form' . DS . $tmpl); JDEBUG ? $_PROFILER->mark('form view before template load') : null; $text = $this->loadTemplate(); if ($params->get('process-jplugins') == 1 || $params->get('process-jplugins') == 2 && $model->_editable === false) { $opt = JRequest::getVar('option'); JRequest::setVar('option', 'com_content'); jimport('joomla.html.html.content'); $text .= '{emailcloak=off}'; $text = JHTML::_('content.prepare', $text); $text = preg_replace('/\\{emailcloak\\=off\\}/', '', $text); JRequest::setVar('option', $opt); } //$text = "<div id=\"fabrik\">$text</div>"; JDEBUG ? $_PROFILER->mark('form view display end') : null; echo $text; }
/** * Get tab categories and merge as necessary to get down to tab limit * * @return array Tabs */ private function getTabCategories() { /** * 2013-07-19 Paul - This function determines the tabs to be shown at the top of the list table. * The tabs are defined by the contents of a user specified field e.g for alphabetic tabs you might * use a calc field with the first character of a surname. * To prevent a list of **/ $params = $this->getParams(); $tabsField = $tabsElName = $this->getTabField(); if (empty($tabsField)) { return array(); } list($tableName, $tabsField) = explode('___', $tabsField); $table = $this->getTable(); if ($tableName != $table->db_table_name) { $this->app->enqueueMessage(sprintf(FText::_('COM_FABRIK_LIST_TABS_TABLE_ERROR'), $tableName, $table->db_table_name), 'error'); return array(); } $tabsMax = (int) $params->get('tabs_max', 10); $tabsAll = (bool) $params->get('tabs_all', '1'); // @FIXME - starting to implement code to handle join elements, not cooked yet $formModel = $this->getFormModel(); $elementModel = $formModel->getElement($tabsElName); $is_join = is_subclass_of($elementModel, 'PlgFabrik_ElementDatabasejoin') || get_class($elementModel) == 'PlgFabrik_ElementDatabasejoin'; if (!$is_join) { // Get values and count in the tab field $db = $this->getDb(); $query = $db->getQuery(true); $query->select(array($tabsField, 'Count(' . $tabsField . ') as count'))->from($db->qn($table->db_table_name))->group($tabsField)->order($tabsField); } else { $this->app->enqueueMessage(sprintf(FText::_('COM_FABRIK_LIST_TABS_TABLE_ERROR'), $tableName, $table->db_table_name), 'error'); $joinTable = $elementModel->getJoinModel()->getJoin(); $fullFk = $joinTable->table_join . '___' . $joinTable->table_join_key; return array(); } /** * Filters include any existing tab filters - so we cannot calculate tabs based on any user set filters * or pre-filters, until we can exclude them from being used here. $this->buildQueryWhere($this->app->input->getInt('incfilters', 1), $query, false); **/ $db->setQuery($query); FabrikHelperHTML::debug($query->dump(), 'list getTabCategories query:' . $table->label); $profiler = JProfiler::getInstance('Application'); JDEBUG ? $profiler->mark('before fabrik list tabs query run') : null; $db->execute(); $counts = $db->loadRowList(); JDEBUG ? $profiler->mark('after fabrik list tabs query run') : null; FabrikHelperHTML::debug($counts, 'list getTabCategories counts: ' . $table->label); /** * We consolidate by finding the two consecutive rows with the smallest total and merging them. * To avoid excessive looping if user tabField is too fragmented, we should skip tabs if * we will iterate more than 100 times. **/ if (count($counts) - $tabsMax > 100) { $this->app->enqueueMessage(sprintf(FText::_('COM_FABRIK_LIST_TABS_MERGE_ERROR'), count($counts), $tabsMax), 'notice'); return array(); } $tabs = array(); if ($tabsAll) { // Set value to null to differentiate between all and empty string values $tabs[] = array(FText::_('COM_FABRIK_LIST_TABS_ALL'), null); } while (count($counts) > $tabsMax) { /** * Primary algorithm is to find the two consecutive rows whose total count is smallest and merge them. * * If this turns out to be too time consuming in real-life scenarios, we can add further optimisation * by adding logic to the loop so that first time through it sums the total of count, and * second time through it merges any consecutive rows whose values total less than a small proportion (say 1/4) * of the total count / tabs. This will not be completely optimum but will be a whole lot quicker for many small * categories than the base iteration. Using 1/4 should result in no more than 3 further iterations per tab to get to * the number of tabs required. In this case we can probably remove the test / error message above. **/ $minCount = 999999999; $minIndex = 0; for ($i = 1; $i < count($counts); $i++) { $totCount = $counts[$i - 1][1] + $counts[$i][1]; if ($totCount < $minCount) { $minCount = $totCount; $minIndex = $i; } } // Merge mins $counts[$minIndex - 1][0] = (array) $counts[$minIndex - 1][0]; $counts[$minIndex][0] = (array) $counts[$minIndex][0]; $counts[$minIndex - 1][0] = array($counts[$minIndex - 1][0][0], end($counts[$minIndex][0])); $counts[$minIndex - 1][1] += $counts[$minIndex][1]; // Array_splice not working as advertised - working like array_slice for some reason!! // $counts = array_splice($counts, $minIndex, 1); unset($counts[$minIndex]); $counts = array_values($counts); } JDEBUG ? $profiler->mark('after fabrik list tabs counts merge') : null; FabrikHelperHTML::debug($counts, 'list getTabCategories merged counts: ' . $table->label); for ($i = 0; $i < count($counts); $i++) { if (is_array($counts[$i][0])) { $tabs[] = array($counts[$i][0][0] . '-' . $counts[$i][0][1], $counts[$i][0]); } else { $tabLabel = empty($counts[$i][0]) ? '-' : $counts[$i][0]; $tabs[] = array($tabLabel, $counts[$i][0]); } } return $tabs; }
/** * Create an array of label/values which will be used to populate the elements filter dropdown * returns only data found in the table you are filtering on * * @param bool $normal do we render as a normal filter or as an advanced search filter * @param string $tableName table name to use - defaults to element's current table * @param string $label field to use, defaults to element name * @param string $id field to use, defaults to element name * @param bool $incjoin include join * * @return array filter value and labels */ protected function filterValueList_Exact($normal, $tableName = '', $label = '', $id = '', $incjoin = true) { $listModel = $this->getListModel(); $fbConfig = JComponentHelper::getParams('com_fabrik'); $fabrikDb = $listModel->getDb(); $table = $listModel->getTable(); $element = $this->getElement(); $origTable = $table->db_table_name; $elName = $this->getFullName(false, true, false); $params = $this->getParams(); $elName2 = $this->getFullName(false, false, false); if (!$this->isJoin()) { $ids = $listModel->getColumnData($elName2); // For ids that are text with apostrophes in for ($x = count($ids) - 1; $x >= 0; $x--) { if ($ids[$x] == '') { unset($ids[$x]); } else { $ids[$x] = addslashes($ids[$x]); } } } $incjoin = $this->isJoin() ? false : $incjoin; /** * filter the drop downs lists if the table_view_own_details option is on * other wise the lists contain data the user should not be able to see * note, this should now use the prefilter data to filter the list */ // Check if the elements group id is on of the table join groups if it is then we swap over the table name $fromTable = $this->isJoin() ? $this->getJoinModel()->getJoin()->table_join : $origTable; $joinStr = $incjoin ? $listModel->_buildQueryJoin() : $this->_buildFilterJoin(); // New option not to order elements - required if you want to use db joins 'Joins where and/or order by statement' $groupBy = $this->getOrderBy('filter'); foreach ($listModel->getJoins() as $aJoin) { // Not sure why the group id key wasnt found - but put here to remove error if (array_key_exists('group_id', $aJoin)) { if ($aJoin->group_id == $element->group_id && $aJoin->element_id == 0) { $fromTable = $aJoin->table_join; $elName = str_replace($origTable . '.', $fromTable . '.', $elName2); } } } $elName = FabrikString::safeColName($elName); if ($label == '') { $label = $this->isJoin() ? $this->getElement()->name : $elName; } if ($id == '') { $id = $this->isJoin() ? 'id' : $elName; } if ($this->encryptMe()) { $secret = JFactory::getConfig()->getValue('secret'); $label = 'AES_DECRYPT(' . $label . ', ' . $fabrikDb->quote($secret) . ')'; $id = 'AES_DECRYPT(' . $id . ', ' . $fabrikDb->quote($secret) . ')'; } $origTable = $tableName == '' ? $origTable : $tableName; /** * $$$ rob - 2nd sql was blowing up for me on my test table - why did we change to it? * http://localhost/fabrik2.0.x/index.php?option=com_fabrik&view=table&listid=12&calculations=0&resetfilters=0&Itemid=255&lang=en * so added test for intial fromtable in join str and if found use origtable */ if (strstr($joinStr, 'JOIN ' . $fabrikDb->quoteName($fromTable))) { $sql = 'SELECT DISTINCT(' . $label . ') AS ' . $fabrikDb->quoteName('text') . ', ' . $id . ' AS ' . $fabrikDb->quoteName('value') . ' FROM ' . $fabrikDb->quoteName($origTable) . $joinStr . "\n"; } else { $sql = 'SELECT DISTINCT(' . $label . ') AS ' . $fabrikDb->quoteName('text') . ', ' . $id . ' AS ' . $fabrikDb->quoteName('value') . ' FROM ' . $fabrikDb->quoteName($fromTable) . $joinStr . "\n"; } if (!$this->isJoin()) { $sql .= 'WHERE ' . $id . ' IN (\'' . implode("','", $ids) . '\')'; } // Apply element where/order by statements to the filter (e.g. dbjoins 'Joins where and/or order by statement') $elementWhere = $this->_buildQueryWhere(array(), true, null, array('mode' => 'filter')); if (JString::stristr($sql, 'WHERE ') && JString::stristr($elementWhere, 'WHERE ')) { // $$$ hugh - only replace the WHERE with AND if it's the first word, so we don't munge sub-queries // $elementWhere = JString::str_ireplace('WHERE ', 'AND ', $elementWhere); $elementWhere = preg_replace("#^(\\s*)(WHERE)(.*)#i", "\$1AND\$3", $elementWhere); } $sql .= ' ' . $elementWhere; $sql .= "\n" . $groupBy; $sql = $listModel->pluginQuery($sql); $fabrikDb->setQuery($sql, 0, $fbConfig->get('filter_list_max', 100)); FabrikHelperHTML::debug($fabrikDb->getQuery(), 'element filterValueList_Exact:'); $rows = $fabrikDb->loadObjectList(); if ($fabrikDb->getErrorNum() != 0) { JError::raiseNotice(500, 'filter query error: ' . $this->getElement()->name . ' ' . $fabrikDb->getErrorMsg()); } return $rows; }
/** * (non-PHPdoc) * @see components/com_fabrik/models/plgFabrik_Element::filterValueList_All() */ protected function filterValueList_All($normal, $tableName = '', $label = '', $id = '', $incjoin = true) { /* * list of all tables that have been joined to - * if duplicated then we need to join using a table alias */ $listModel =& $this->getlistModel(); $table =& $listModel->getTable(); $origTable = $table->db_table_name; $fabrikDb =& $listModel->getDb(); $params =& $this->getParams(); $joinTable = $params->get('join_db_name'); $joinKey = $this->getJoinValueColumn(); $joinVal = $this->getJoinLabelColumn(); $join =& $this->getJoin(); $joinTableName = $join->table_join_alias; if ($joinTable == '') { $joinTable = $joinTableName; } // $$$ hugh - select all values for performance gain over selecting distinct records from recorded data $sql = "SELECT DISTINCT( {$joinVal} ) AS text, {$joinKey} AS value \n FROM " . $db->nameQuote($joinTable) . " AS " . $db->nameQuote($joinTableName) . " \n "; $where = $this->_buildQueryWhere(); //ensure table prefilter is applied to query $prefilterWhere = $listModel->_buildQueryPrefilterWhere($this); $elementName =& FabrikString::safeColName($this->getFullName(false, false, false)); // $$$ hugh - $joinKey is already in full `table`.`element` format from getJoinValueColumn() //$prefilterWhere = str_replace($elementName, "`$joinTableName`.`$joinKey`", $prefilterWhere); $prefilterWhere = str_replace($elementName, $joinKey, $prefilterWhere); if (trim($where) == '') { $prefilterWhere = str_replace('AND', 'WHERE', $prefilterWhere); } $where .= $prefilterWhere; $sql .= $where; if (!JString::stristr($where, 'order by')) { $order = $params->get('filter_groupby', 'text') == 'text' ? $joinKey : $joinVal; $sql .= " ORDER BY {$order} ASC "; } $sql = $listModel->pluginQuery($sql); $fabrikDb->setQuery($sql); FabrikHelperHTML::debug($fabrikDb->getQuery(), 'fabrikdatabasejoin getFilter'); return $fabrikDb->loadObjectList(); }
/** * Add a debug out put section * * @param mixed $content string/object * @param string $title debug title * * @return void */ public static function debug($content, $title = 'output:') { $config = JComponentHelper::getParams('com_fabrik'); if ($config->get('use_fabrikdebug') == 0) { return; } if (JRequest::getBool('fabrikdebug', 0, 'request') != 1) { return; } if (JRequest::getVar('format') == 'raw') { return; } echo '<div class="fabrikDebugOutputTitle">' . $title . '</div>'; echo '<div class="fabrikDebugOutput fabrikDebugHidden">'; if (is_object($content) || is_array($content)) { echo '<pre>' . htmlspecialchars(print_r($content, true)) . '</pre>'; } else { echo htmlspecialchars($content); } echo '</div>'; if (!isset(self::$debug)) { self::$debug = true; $document = JFactory::getDocument(); $style = ".fabrikDebugOutputTitle{padding:5px;background:#efefef;color:#333;border:1px solid #999;cursor:pointer}"; $style .= ".fabrikDebugOutput{padding:5px;background:#efefef;color:#999;}"; $style .= ".fabrikDebugOutput pre{padding:5px;background:#efefef;color:#999;}"; $style .= ".fabrikDebugHidden{display:none}"; self::addStyleDeclaration($style); $script = "head.ready(function() {\n\t\t\t\$\$('.fabrikDebugOutputTitle').each(function(title) {\n\t\t\t\ttitle.addEvent('click', function(e) {\n\t\t\t\t\ttitle.getNext().toggleClass('fabrikDebugHidden');\n\t\t\t\t});\n\t\t\t});\n\t\t\t})"; self::addScriptDeclaration($script); } }
/** * filter the list data * @return null */ function filter() { $modelName = JRequest::getVar('view', 'list', 'default', 'cmd'); $model = $this->getModel($modelName, 'FabrikFEModel'); $model->setId(JRequest::getInt('listid')); FabrikHelperHTML::debug('', 'list model: getRequestData'); $request = $model->getRequestData(); $model->storeRequestData($request); // $$$ rob pass in the model otherwise display() rebuilds it and the request data is rebuilt return $this->display($model); }
/** * this really does get just the default value (as defined in the element's settings) * @param array data to use as parsemessage for placeholder * @return mixed */ function getDefaultValue($data = array()) { if (!isset($this->_default)) { $w = new FabrikWorker(); $element = $this->getElement(); $default = $w->parseMessageForPlaceHolder($element->default, $data); if ($element->eval == "1") { FabrikHelperHTML::debug($default, 'element eval default:' . $element->label); $default = @eval(stripslashes($default)); FabrikWorker::logEval($default, 'Caught exception on eval of ' . $element->name . ': %s'); } $this->_default = $default; } return $this->_default; }
/** * Add a debug out put section * * @param mixed $content String/object * @param string $title Debug title * * @return void */ public static function debug($content, $title = 'output:') { $config = JComponentHelper::getParams('com_fabrik'); $app = JFactory::getApplication(); $input = $app->input; if ($config->get('use_fabrikdebug') == 0) { return; } if ($input->getBool('fabrikdebug', 0, 'request') != 1) { return; } if ($input->get('format') == 'raw') { return; } echo '<div class="fabrikDebugOutputTitle">' . $title . '</div>'; echo '<div class="fabrikDebugOutput fabrikDebugHidden">'; if (is_object($content) || is_array($content)) { echo '<pre>' . htmlspecialchars(print_r($content, true)) . '</pre>'; } else { // Remove any <pre> tags provided by e.g. JQuery::dump $content = preg_replace('/(^\\s*<pre( .*)?>)|(<\\/pre>\\s*$)/i', '', $content); echo htmlspecialchars($content); } echo '</div>'; if (!isset(self::$debug)) { self::$debug = true; $style = ".fabrikDebugOutputTitle{padding:5px;background:#efefef;color:#333;border:1px solid #999;cursor:pointer}"; $style .= ".fabrikDebugOutput{padding:5px;background:#efefef;color:#999;}"; $style .= ".fabrikDebugOutput pre{padding:5px;background:#efefef;color:#999;}"; $style .= ".fabrikDebugHidden{display:none}"; self::addStyleDeclaration($style); $script = "window.addEvent('domready', function() {\r\n\t\t\t\tdocument.getElements('.fabrikDebugOutputTitle').each(function (title) {\r\n\t\t\t\ttitle.addEvent('click', function (e) {\r\n\t\t\t\ttitle.getNext().toggleClass('fabrikDebugHidden');\r\n\t\t});\r\n\t\t});\r\n\t\t})"; self::addScriptDeclaration($script); } }
/** * Main setup routine for displaying the form/detail view * * @param string $tpl template * * @return void */ public function display($tpl = null) { $profiler = JProfiler::getInstance('Application'); $input = $this->app->input; $w = new FabrikWorker(); /** @var FabrikFEModelForm $model */ $model = $this->getModel('form'); if (!$model) { // Dodgy URL - can't find the form name see https://github.com/Fabrik/fabrik/issues/1248 return; } $model->isMambot = $this->isMambot; if ($model->render() === false) { return false; } $this->isMultiPage = $model->isMultiPage(); list($this->plugintop, $this->pluginbottom, $this->pluginend) = $model->getFormPluginHTML(); $listModel = $model->getlistModel(); if (!$this->canAccess()) { return false; } JDEBUG ? $profiler->mark('form view before join group ids got') : null; if (!$listModel->noTable()) { $joins = $listModel->getJoins(); $model->getJoinGroupIds($joins); } $params = $model->getParams(); $this->setTitle($w, $params); FabrikHelperHTML::debug($params->get('note'), 'note'); $params->def('icons', $this->app->get('icons')); $params->set('popup', $input->get('tmpl') == 'component' ? 1 : 0); $this->editable = $model->isEditable(); $form = $this->prepareFormTable(); $clearErrors = false; // Module rendered without ajax, we need to assign the session errors back into the model if ($model->isMambot) { $this->package = $this->app->getUserState('com_fabrik.package', 'fabrik'); $context = $model->getSessionContext(); $model->errors = $this->session->get($context . 'errors', array()); $clearErrors = true; } JDEBUG ? $profiler->mark('form view before validation classes loaded') : null; $tmpl = $model->getTmpl(); $this->tmpl = $tmpl; $this->_addButtons(); JDEBUG ? $profiler->mark('form view before group view got') : null; $this->groups = $model->getGroupView($tmpl); $this->_repeatGroupButtons($tmpl); JDEBUG ? $profiler->mark('form view after group view got') : null; $this->data = $model->tmplData; $this->params = $params; $this->tipLocation = $params->get('tiplocation'); FabrikHelperHTML::debug($this->groups, 'form:view:groups'); $this->setTmplFolders($tmpl); $this->_addJavascript($listModel->getId()); JDEBUG ? $profiler->mark('form view: after add js') : null; $this->_loadTmplBottom($form); JDEBUG ? $profiler->mark('form view: after tmpl bottom loaded') : null; $this->form = $form; JDEBUG ? $profiler->mark('form view: form assigned as ref') : null; $list = new stdClass(); $list->id = $form->record_in_database ? $model->getListModel()->getTable()->id : 0; $this->list = $list; JDEBUG ? $profiler->mark('form view: before getRelatedTables()') : null; $this->linkedTables = $model->getRelatedTables(); JDEBUG ? $profiler->mark('form view: after getRelatedTables()') : null; $this->setMessage(); // If rendered as a module (non ajax) and we have inserted the session errors, clear them from the session. if ($clearErrors) { $model->clearErrors(); } JDEBUG ? $profiler->mark('form view before template load') : null; }