/** * Render an item in the backend (list/tree) * * @param InterfaceGeneralModel $objModelRow the model to be drawn * * @return void */ protected function drawItem(InterfaceGeneralModel $objModelRow) { $objNativeItem = $objModelRow->getItem(); $objMetaModel = $objNativeItem->getMetaModel(); $objView = MetaModelRenderSettingsFactory::byId($objMetaModel, $this->intViewId); if ($objView) { $objTemplate = new MetaModelTemplate($objView->get('template')); } else { return 'No rendersetting defined.'; } if ($objMetaModel->hasVariants() && !$objNativeItem->isVariantBase()) { // create a clone to have a seperate copy of the object as we are going to manipulate it here. $objView = clone $objView; // loop over all attributes and remove those from rendering that are not desired. foreach (array_keys($objMetaModel->getInVariantAttributes()) as $strAttrName) { $objView->setSetting($strAttrName, NULL); } } $this->prepareTemplate($objTemplate, $objNativeItem, $objView); return $objTemplate->parse('html5', true); }
/** * Called when the attribute has been saved. * * @param InterfaceGeneralModel $objModel The model that has been updated. * * @param DataContainer $objDC the data container that issued this callback. */ public function onSaveCallback($objModel, $objDC) { /** * The currently edited field. * * @var IMetaModelAttribute */ $objField = self::$objCurrentField; $arrNewField = $objModel->getPropertiesAsArray(); if ($objField) { $oldType = $objField->get('type'); } else { $oldType = null; } if ($oldType != $arrNewField['type']) { // destroy old instance... if ($objField) { $objField->destroyAUX(); } // ... prepare new instance. $objField = MetaModelAttributeFactory::createFromArray($arrNewField); // create new instance' aux info. if ($objField) { self::$objCurrentField = $objField; $objField->initializeAUX(); } } if ($objField) { // now loop over all values and update the meta in the instance. foreach ($arrNewField as $strKey => $varValue) { $objField->handleMetaChange($strKey, $varValue); } } }
/** * Compile buttons from the table configuration array and return them as HTML * * @param InterfaceGeneralModel $objModelRow * @param string $strTable * @param array $arrRootIds * @param boolean $blnCircularReference * @param array $arrChildRecordIds * @param int $strPrevious * @param int $strNext * @return string */ protected function generateButtons(InterfaceGeneralModel $objModelRow, $strTable, $arrRootIds = array(), $blnCircularReference = false, $arrChildRecordIds = null, $strPrevious = null, $strNext = null) { $arrDCA = $this->getDC()->getDCA(); if (!count($arrDCA['list']['operations'])) { return ''; } $return = ''; foreach ($arrDCA['list']['operations'] as $k => $v) { // Check if we have a array if (!is_array($v)) { $v = array($v); } // Set basic informations $label = strlen($v['label'][0]) ? $v['label'][0] : $k; $title = sprintf(strlen($v['label'][1]) ? $v['label'][1] : $k, $objModelRow->getID()); $attributes = strlen($v['attributes']) ? ' ' . ltrim(sprintf($v['attributes'], $objModelRow->getID(), $objModelRow->getID())) : ''; // Call a custom function instead of using the default button $strButtonCallback = $this->getDC()->getCallbackClass()->buttonCallback($objModelRow, $v, $label, $title, $attributes, $strTable, $arrRootIds, $arrChildRecordIds, $blnCircularReference, $strPrevious, $strNext); if (!is_null($strButtonCallback)) { $return .= ' ' . trim($strButtonCallback); continue; } // Generate all buttons except "move up" and "move down" buttons if ($k != 'move' && $v != 'move') { switch ($k) { // Cute needs some special informations case 'cut': // Get dataprovider from current and parent $strCDP = $objModelRow->getProviderName(); $strPDP = $objModelRow->getMeta(DCGE::MODEL_PTABLE); $strAdd2Url = ""; // Add url + id + currentDataProvider $strAdd2Url .= $v['href'] . '&cdp=' . $strCDP; // Add parent provider if exsists if ($strPDP != null) { $strPDP = $strPDP; $strAdd2Url .= '&pdp=' . $strPDP; } // If we have a id add it, used for mode 4 and all parent -> current views if (strlen($this->Input->get('id')) != 0) { $strAdd2Url .= '&id=' . $this->Input->get('id'); } // Source is the id of the element which should move $strAdd2Url .= '&source=' . $objModelRow->getID(); // Build whole button mark up $return .= ' <a href="' . $this->addToUrl($strAdd2Url) . '" title="' . specialchars($title) . '"' . $attributes . '>' . $this->generateImage($v['icon'], $label) . '</a>'; break; default: $idParam = $v['idparam'] ? 'id=&' . $v['idparam'] : 'id'; $strUrl = $this->addToUrl($v['href'] . '&' . $idParam . '=' . $objModelRow->getID()); $return .= ' <a href="' . $strUrl . '" title="' . specialchars($title) . '"' . $attributes . '>' . $this->generateImage($v['icon'], $label) . '</a>'; break; } continue; } $arrRootIds = is_array($arrRootIds) ? $arrRootIds : array($arrRootIds); foreach (array('up', 'down') as $dir) { $label = strlen($GLOBALS['TL_LANG'][$strTable][$dir][0]) ? $GLOBALS['TL_LANG'][$strTable][$dir][0] : $dir; $title = strlen($GLOBALS['TL_LANG'][$strTable][$dir][1]) ? $GLOBALS['TL_LANG'][$strTable][$dir][1] : $dir; $label = $this->generateImage($dir . '.gif', $label); $href = strlen($v['href']) ? $v['href'] : '&act=move'; if ($dir == 'up') { $return .= (is_numeric($strPrevious) && (!in_array($objModelRow->getID(), $arrRootIds) || !count($GLOBALS['TL_DCA'][$strTable]['list']['sorting']['root'])) ? ' <a href="' . $this->addToUrl($href . '&id=' . $objModelRow->getID()) . '&sid=' . intval($strPrevious) . '" title="' . specialchars($title) . '"' . $attributes . '>' . $label . '</a> ' : $this->generateImage('up_.gif')) . ' '; continue; } $return .= (is_numeric($strNext) && (!in_array($objModelRow->getID(), $arrRootIds) || !count($GLOBALS['TL_DCA'][$strTable]['list']['sorting']['root'])) ? ' <a href="' . $this->addToUrl($href . '&id=' . $objModelRow->getID()) . '&sid=' . intval($strNext) . '" title="' . specialchars($title) . '"' . $attributes . '>' . $label . '</a> ' : $this->generateImage('down_.gif')) . ' '; } } // Add paste into/after icons if ($this->getDC()->isClipboard()) { $arrClipboard = $this->getDC()->getClipboard(); // Check if the id is in the ignore list if ($arrClipboard['mode'] == 'cut' && in_array($objModelRow->getID(), $arrClipboard['ignoredIDs'])) { switch ($this->getDC()->arrDCA['list']['sorting']['mode']) { default: case 4: $return .= ' '; $return .= $imagePasteAfter = $this->generateImage('pasteafter_.gif', $GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteafter'][0], 'class="blink"'); break; case 5: $return .= ' '; $return .= $imagePasteAfter = $this->generateImage('pasteafter_.gif', $GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteafter'][0], 'class="blink"'); $return .= ' '; $return .= $imagePasteInto = $this->generateImage('pasteinto_.gif', $GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteinto'][0], 'class="blink"'); break; } } else { // $strAdd2Url = ""; // $strAdd2Url .= 'act=' . $arrClipboard['mode']; // $strAdd2Url .= 'act=' . $arrClipboard['mode']; // // Switch mode // Add ext. information $strAdd2UrlAfter = 'act=' . $arrClipboard['mode'] . '&mode=1&pid=' . $arrClipboard['id'] . '&after=' . $objModelRow->getID() . '&source=' . $arrClipboard['source'] . '&childs=' . $arrClipboard['childs']; $strAdd2UrlInto = 'act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $arrClipboard['id'] . '&after=' . $objModelRow->getID() . '&source=' . $arrClipboard['source'] . '&childs=' . $arrClipboard['childs']; if ($arrClipboard['pdp'] != '') { $strAdd2UrlAfter .= '&pdp=' . $arrClipboard['pdp']; $strAdd2UrlInto .= '&pdp=' . $arrClipboard['pdp']; } if ($arrClipboard['cdp'] != '') { $strAdd2UrlAfter .= '&cdp=' . $arrClipboard['cdp']; $strAdd2UrlInto .= '&cdp=' . $arrClipboard['cdp']; } switch ($this->getDC()->arrDCA['list']['sorting']['mode']) { default: case 4: $imagePasteAfter = $this->generateImage('pasteafter.gif', $GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteafter'][0], 'class="blink"'); $strPasteBtt = ' <a href="' . $this->addToUrl($strAdd2UrlAfter) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteafter'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a> '; // Callback for paste btt $strButtonCallback = $this->getDC()->getCallbackClass()->pasteButtonCallback($this->objDC, $objModelRow->getPropertiesAsArray(), $strTable, false, $arrClipboard, null, null); if ($strButtonCallback === false) { $return .= $strPasteBtt; } else { $return .= $strButtonCallback; } break; case 5: // Btn paste after. $imagePasteAfter = $this->generateImage('pasteafter.gif', $GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteafter'][0], 'class="blink"'); $strPasteBtt = ' <a href="' . $this->addToUrl($strAdd2UrlAfter) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteafter'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a> '; // Btn paste into. $imagePasteInto = $this->generateImage('pasteinto.gif', $GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteinto'][0], 'class="blink"'); $strPasteBtt .= ' <a href="' . $this->addToUrl($strAdd2UrlInto) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->getDC()->getTable()]['pasteinto'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteInto . '</a> '; // Callback for paste btn. $strButtonCallback = $this->getDC()->getCallbackClass()->pasteButtonCallback($this->objDC, $objModelRow->getPropertiesAsArray(), $strTable, false, $arrClipboard, null, null); if ($strButtonCallback === false) { $return .= $strPasteBtt; } else { $return .= $strButtonCallback; } break; } } } return trim($return); }
/** * Check if two models have the same values in all properties. * * @param InterfaceGeneralModel $objModel1 The first model to compare. * * @param InterfaceGeneralModel $objModel2 The second model to compare. * * @return boolean True - If both models are same, false if not. */ public function sameModels($objModel1, $objModel2) { foreach ($objModel1 as $key => $value) { if ($key == "id") { continue; } if (is_array($value)) { if (!is_array($objModel2->getProperty($key))) { return false; } if (serialize($value) != serialize($objModel2->getProperty($key))) { return false; } } else { if ($value != $objModel2->getProperty($key)) { return false; } } } return true; }
/** * Check if two models have the same values in all properties. * * @param InterfaceGeneralModel $objModel1 The first model to compare. * * @param InterfaceGeneralModel $objModel2 The second model to compare. * * @return boolean True - If both models are same, false if not. */ public function sameModels($objModel1, $objModel2) { /** * These must be: * @var GeneralModelMetaModel $objModel1 * @var GeneralModelMetaModel $objModel2 */ $objNative1 = $objModel1->getItem(); $objNative2 = $objModel2->getItem(); if ($objNative1->getMetaModel() != $objNative2->getMetaModel()) { return false; } foreach ($objNative1->getMetaModel()->getAttributes() as $objAttribute) { if ($objNative1->get($objAttribute->getColName()) != $objNative2->get($objAttribute->getColName())) { return false; } } return true; }
/** * Insert a record at the specific position. * * Move all records at position >= $index one index up. * If $index is out of bounds, just add at the end (does not fill with empty records!). * * @param integer $intIndex The index where the model shall be placed. * * @param InterfaceGeneralModel $objModel The model to insert. * * @return void */ public function insert($intIndex, InterfaceGeneralModel $objModel) { if ($objModel->hasProperties()) { array_insert($this->arrCollection, $intIndex, array($objModel)); } }
public function sortCollection(InterfaceGeneralModel $a, InterfaceGeneralModel $b) { if ($a->getProperty($this->arrColSort['field']) == $b->getProperty($this->arrColSort['field'])) { return 0; } if (!$this->arrColSort['reverse']) { return $a->getProperty($this->arrColSort['field']) < $b->getProperty($this->arrColSort['field']) ? -1 : 1; } else { return $a->getProperty($this->arrColSort['field']) < $b->getProperty($this->arrColSort['field']) ? 1 : -1; } }
/** * Get for a field the readable value * * @param string $strFieldName * @param mixed $mixValue * @return mixed [string|int] */ public function getReadableFieldValue($strFieldName, $mixValue) { if (!key_exists($strFieldName, $this->arrDCA['fields'])) { return $mixValue; } // Load the config for current field $arrFieldConfig = $this->arrDCA['fields'][$strFieldName]; $mixModelField = $this->objCurrentModel->getProperty($strFieldName); /* * @todo Maybe the controlle should handle this ? */ if (isset($arrFieldConfig['foreignKey'])) { $temp = array(); $chunks = explode('.', $arrFieldConfig['foreignKey'], 2); foreach ((array) $value as $v) { // $objKey = $this->Database->prepare("SELECT " . $chunks[1] . " AS value FROM " . $chunks[0] . " WHERE id=?") // ->limit(1) // ->execute($v); // // if ($objKey->numRows) // { // $temp[] = $objKey->value; // } } // $row[$i] = implode(', ', $temp); } else { if (is_array($mixValue)) { foreach ($mixValue as $kk => $vv) { if (is_array($vv)) { $vals = array_values($vv); $mixValue[$kk] = $vals[0] . ' (' . $vals[1] . ')'; } } return implode(', ', $mixValue); } else { if ($arrFieldConfig['eval']['rgxp'] == 'date') { return $this->parseDate($GLOBALS['TL_CONFIG']['dateFormat'], $mixValue); } else { if ($arrFieldConfig['eval']['rgxp'] == 'time') { return $this->parseDate($GLOBALS['TL_CONFIG']['timeFormat'], $mixValue); } else { if ($arrFieldConfig['eval']['rgxp'] == 'datim' || in_array($arrFieldConfig['flag'], array(5, 6, 7, 8, 9, 10)) || $strFieldName == 'tstamp') { return $this->parseDate($GLOBALS['TL_CONFIG']['datimFormat'], $mixValue); } else { if ($arrFieldConfig['inputType'] == 'checkbox' && !$arrFieldConfig['eval']['multiple']) { return strlen($mixValue) ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']; } else { if ($arrFieldConfig['inputType'] == 'textarea' && ($arrFieldConfig['eval']['allowHtml'] || $arrFieldConfig['eval']['preserveTags'])) { return nl2br_html5(specialchars($mixValue)); } else { if (is_array($arrFieldConfig['reference'])) { return isset($arrFieldConfig['reference'][$mixModelField]) ? is_array($arrFieldConfig['reference'][$mixModelField]) ? $arrFieldConfig['reference'][$mixModelField][0] : $arrFieldConfig['reference'][$mixModelField] : $mixModelField; } else { if (array_is_assoc($arrFieldConfig['options'])) { return $arrFieldConfig['options'][$mixModelField]; } else { return $mixValue; } } } } } } } } } }
/** * Retrieve the current values of the model and create the title widget information. * * @param InterfaceGeneralModel $objModel the current Model active in the DC. * * @param DC_General $objDC the Datacontainer calling us. */ public function onModelUpdatedCallback($objModel, $objDC) { // do nothing if not in edit mode. if (!($this->Input->get('act') == 'create' || $this->Input->get('act') == 'edit')) { return; } $this->objectsFromUrl($objDC); $GLOBALS['TL_DCA']['tl_metamodel_dcasetting']['fields']['legendtitle'] = array_replace_recursive(parent::makeMultiColumnName($this->objMetaModel, $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_langcode'], $GLOBALS['TL_LANG']['tl_metamodel_dcasetting']['name_value'], false, $objModel->getProperty('legendtitle')), $GLOBALS['TL_DCA']['tl_metamodel_dcasetting']['fields']['legendtitle']); }
/** * Save a model to the database. * * In general, this method fetches the solely property "rows" from the model and updates the local table against * these contents. * * The parent id (id of the model) will get checked and reflected also for new items. * * When rows with duplicate ids are encountered (like from MCW for example), the dupes are inserted as new rows. * * @param InterfaceGeneralModel $objItem The model to save. * * @param bool $recursive Ignored as not relevant in this data provider. * * @return InterfaceGeneralModel The passed Model. * * @throws Exception When the passed model does not contain a property named "rows", an Exception is thrown. */ public function save(InterfaceGeneralModel $objItem, $recursive = false) { $arrData = $objItem->getProperty('rows'); if (!($objItem->getID() && $arrData)) { throw new Exception('invalid input data in model.', 1); } $arrKeep = array(); foreach ($arrData as $i => $arrRow) { // TODO: add an option to restrict this to some allowed fields? $arrSQL = $arrRow; // update all. $intId = intval($arrRow['id']); // Work around the fact that multicolumnwizard does not clear any hidden fields when copying a dataset. // therefore we do consider any dupe as new dataset and save it accordingly. if (in_array($intId, $arrKeep)) { $intId = 0; unset($arrSQL['id']); } if ($intId > 0) { $this->objDatabase->prepare(sprintf('UPDATE tl_metamodel_dca_combine %%s WHERE id=? AND %s=?', $this->strGroupCol))->set($arrSQL)->execute($intId, $objItem->getId()); $arrKeep[] = $intId; } else { // force group col value: $arrSQL[$this->strGroupCol] = $objItem->getId(); $arrKeep[] = $this->objDatabase->prepare('INSERT INTO tl_metamodel_dca_combine %s')->set($arrSQL)->execute()->insertId; } } // house keeping, kill the rest. $this->objDatabase->prepare(sprintf('DELETE FROM tl_metamodel_dca_combine WHERE %s=? AND id NOT IN (%s)', $this->strGroupCol, implode(',', $arrKeep)))->execute($objItem->getId()); return $objItem; }
/** * Call the group callback. * * @param type $group TODO: document parameter $group * * @param type $mode TODO: document parameter $mode * * @param type $field TODO: document parameter $field * * @param InterfaceGeneralModel $objModelRow * * @return type TODO: document result */ public function groupCallback($group, $mode, $field, $objModelRow) { // Load DCA $arrDCA = $this->objDC->getDCA(); $currentGroup = $group; // Check Callback if (is_array($arrDCA['list']['label']['group_callback'])) { $strClass = $arrDCA['list']['label']['group_callback'][0]; $strMethod = $arrDCA['list']['label']['group_callback'][1]; $this->import($strClass); $currentGroup = $this->{$strClass}->{$strMethod}($currentGroup, $mode, $field, $objModelRow->getPropertiesAsArray(), $this); if ($currentGroup == null) { $group = $currentGroup; } } return $group; }