Source of file ElementAdmin.php
Size: 27,489 Bytes - Last Modified: 2016-05-18T03:08:26+02:00
buildproject/core/module_pages/admin/ElementAdmin.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792 | <?php /*"****************************************************************************************************** * (c) 2004-2006 by MulchProductions, www.mulchprod.de * * (c) 2007-2016 by Kajona, www.kajona.de * * Published under the GNU LGPL v2.1, see /system/licence_lgpl.txt * *-------------------------------------------------------------------------------------------------------* * $Id$ * ********************************************************************************************************/ namespace Kajona\Pages\Admin; use Kajona\Pages\Admin\Formentries\FormentryTemplate; use Kajona\Pages\System\PagesPage; use Kajona\Search\System\SearchResult; use Kajona\System\Admin\AdminController; use Kajona\System\Admin\AdminFormgenerator; use Kajona\System\Admin\Formentries\FormentryDate; use Kajona\System\Admin\Formentries\FormentryHidden; use Kajona\System\Admin\Formentries\FormentryText; use Kajona\System\System\Carrier; use Kajona\System\System\Exception; use Kajona\System\System\Link; use Kajona\System\System\Objectfactory; use Kajona\System\System\OrmBase; use Kajona\System\System\OrmObjectinit; use Kajona\System\System\OrmObjectlist; use Kajona\System\System\OrmObjectupdate; use Kajona\System\System\OrmRowcache; use Kajona\System\System\Reflection; use Kajona\System\System\Resourceloader; use Kajona\System\System\SearchPortalobjectInterface; use Kajona\System\System\SystemModule; use Kajona\System\System\ValidatorInterface; /** * The base class for all page-elements * * @author sidler@mulchprod.de * @abstract * * @module elements * @moduleId _pages_elemente_modul_id_ */ abstract class ElementAdmin extends AdminController implements SearchPortalobjectInterface { const STR_ANNOTATION_ELEMENTCONTENTTITLE = "@elementContentTitle"; private $bitDoValidation = false; protected $arrParamData = array(); /** * @var AdminFormgenerator */ private $objAdminForm = null; /** * Holds the content generated by the element to be places within the (hidden) system-form * elements aka. optional elements. * * @var string */ private $strSystemFormElements = ""; private $arrElementData = array(); private $arrValidationErrors = array(); /** * Constructor */ public function __construct($strSystemid = "") { parent::__construct(); if (validateSystemid($strSystemid)) { $this->loadElementData(); } } /** * @return AdminFormgenerator|null */ public function getAdminForm() { if ($this->objAdminForm == null) { $objAnnotations = new Reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(OrmBase::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) == 0) { return null; } $this->objAdminForm = new AdminFormgenerator("", $this); $this->objAdminForm->generateFieldsFromObject(); } return $this->objAdminForm; } /** * Legacy method for elements not yet supporting the annotation based forms / content updates * * @param array $arrElementData * * @deprecated * @return string */ public function getEditForm($arrElementData) { } /** * Hook-method to modify the form generated based on the current elements' annotations * Overwrite if required. * * @param AdminFormgenerator $objForm * * @return AdminFormgenerator */ protected function updateEditForm(AdminFormgenerator $objForm) { return $objForm; } /** * Forces the element to return a form and adds als stuff needed by the system to handle the request properly * * @param string $strMode edit || new * * @return string */ final public function actionEdit($strMode = "edit") { //split modes - legacy definitions or coooooool declarative processing $objAnnotations = new Reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(OrmBase::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) == 0) { return $this->generateLegacyEdit($strMode); } if ($strMode == "edit") { $this->loadElementData(); $objORM = new OrmObjectinit($this); $objORM->initObjectFromDb(); } $objForm = $this->getAdminForm(); //validation errors? if ($this->bitDoValidation) { $objForm->validateForm(); } $bitShow = false; $objStartDate = null; if (isset($this->arrElementData["system_date_start"]) && $this->arrElementData["system_date_start"] > 0) { $objStartDate = new \Kajona\System\System\Date($this->arrElementData["system_date_start"]); $bitShow = true; } $objEndDate = null; if (isset($this->arrElementData["system_date_end"]) && $this->arrElementData["system_date_end"] > 0) { $objEndDate = new \Kajona\System\System\Date($this->arrElementData["system_date_end"]); $bitShow = true; } $strInternalTitle = (isset($this->arrElementData["page_element_ph_title"]) ? $this->arrElementData["page_element_ph_title"] : ""); if ($strInternalTitle != "") { $bitShow = true; } // hide template chooser when there is only one template available foreach ($objForm->getArrFields() as $objOneField) { if ($objOneField instanceof FormentryTemplate && count($objOneField->getArrKeyValues()) <= 1) { $objForm->addFieldToHiddenGroup($objOneField); } } $objForm->addFieldToHiddenGroup(new FormentryText("", "page_element_ph_title"))->setStrLabel($this->getLang("page_element_ph_title", "pages"))->setStrValue($strInternalTitle); $objForm->addFieldToHiddenGroup(new FormentryDate("", "start"))->setStrLabel($this->getLang("page_element_start", "pages"))->setStrValue($objStartDate); $objForm->addFieldToHiddenGroup(new FormentryDate("", "end"))->setStrLabel($this->getLang("page_element_end", "pages"))->setStrValue($objEndDate); $objForm->setBitHiddenElementsVisible($bitShow); $objForm->setStrHiddenGroupTitle($this->getLang("page_element_system_folder", "pages")); //Language is placed right here instead as a hidden field if ($strMode == "edit") { $objForm->addField(new FormentryHidden("", "page_element_ph_language"))->setStrValue($this->arrElementData["page_element_ph_language"]); } else { $objForm->addField(new FormentryHidden("", "page_element_ph_language"))->setStrValue($this->getLanguageToWorkOn()); } $objForm->addField(new FormentryHidden("", "placeholder"))->setStrValue($this->getParam("placeholder")); $objForm->addField(new FormentryHidden("", "systemid"))->setStrValue($this->getSystemid()); $objForm->addField(new FormentryHidden("", "mode"))->setStrValue($strMode); $objForm->addField(new FormentryHidden("", "element"))->setStrValue($this->getParam("element")); $objForm->addField(new FormentryHidden("", "blocks"))->setStrValue($this->getParam("blocks")); $objForm->addField(new FormentryHidden("", "block"))->setStrValue($this->getParam("block")); //An finally the submit Button if ($this->getParam("pe") != "") { $objForm->addField(new FormentryHidden("", "peClose"))->setStrValue("1")->setStrEntryName("peClose"); } $strReturn = $objForm->renderForm(getLinkAdminHref("pages_content", "saveElement")); return $strReturn; } /** * Method still being kept for legacy elements, so admin-elements not yet switched to annotations * * @param string $strMode * * @return string */ private function generateLegacyEdit($strMode = "edit") { $strReturn = ""; //Right before we do anything, load the data of the current element $arrElementData = $this->arrElementData; //Load the form generated by the element $strFormElement = $this->getEditForm(array_merge($arrElementData, $this->getAllParams())); //Start by creating the form & action $strReturn .= $this->objToolkit->formHeader(getLinkAdminHref("pages_content", "saveElement"), "elEditForm"); //validation errors? if ($this->bitDoValidation) { $this->validateForm(); } $strReturn .= $this->objToolkit->getValidationErrors($this, "saveElement"); //add a folder containing optional system-fields $strSystemFields = ""; $bitShow = false; $objStartDate = null; if (isset($arrElementData["system_date_start"]) && $arrElementData["system_date_start"] > 0) { $objStartDate = new \Kajona\System\System\Date($arrElementData["system_date_start"]); $bitShow = true; } $objEndDate = null; if (isset($arrElementData["system_date_end"]) && $arrElementData["system_date_end"] > 0) { $objEndDate = new \Kajona\System\System\Date($arrElementData["system_date_end"]); $bitShow = true; } $strInternalTitle = (isset($arrElementData["page_element_ph_title"]) ? $arrElementData["page_element_ph_title"] : ""); if ($strInternalTitle != "") { $bitShow = true; } $strSystemFields .= $this->objToolkit->formInputText("page_element_ph_title", $this->getLang("page_element_ph_title", "pages"), $strInternalTitle); $strSystemFields .= $this->objToolkit->formDateSingle("start", $this->getLang("page_element_start", "pages"), $objStartDate); $strSystemFields .= $this->objToolkit->formDateSingle("end", $this->getLang("page_element_end", "pages"), $objEndDate); //add content from sub-classes $strSystemFields .= $this->strSystemFormElements; $strReturn .= $this->objToolkit->formOptionalElementsWrapper($strSystemFields, $this->getLang("page_element_system_folder", "pages"), $bitShow); //Adding the element-stuff $strReturn .= $strFormElement; //Language is placed right here instead as a hidden field if ($strMode == "edit") { $strReturn .= $this->objToolkit->formInputHidden("page_element_ph_language", $arrElementData["page_element_ph_language"]); } else { $strReturn .= $this->objToolkit->formInputHidden("page_element_ph_language", $this->getLanguageToWorkOn()); } $strReturn .= $this->objToolkit->formInputHidden("placeholder", $this->getParam("placeholder")); $strReturn .= $this->objToolkit->formInputHidden("systemid", $this->getSystemid()); $strReturn .= $this->objToolkit->formInputHidden("mode", $strMode); $strReturn .= $this->objToolkit->formInputHidden("element", $this->getParam("element")); //An finally the submit Button $strEventhandler = ""; if ($this->getParam("pe") == 1) { $strReturn .= $this->objToolkit->formInputHidden("peClose", "1"); } $strReturn .= $this->objToolkit->formInputSubmit($this->getLang("commons_save"), "Submit", $strEventhandler); $strReturn .= $this->objToolkit->formClose(); //and close the element return $strReturn; } /** * Overwrite this function, if you want to validate passed form-input * * @return mixed * @deprecated */ public function getRequiredFields() { return array(); } /** * Method used to validate posted form-values. * NOTE: To work with this method, the derived class needs to implement * a method "getRequiredFields()", returning an array of field to validate. * The array returned by getRequiredFields() has to fit the format * [fieldname] = type, whereas type can be one of * string, number, email, folder, systemid * The array saved in $this->$arrValidationErrors return by this method is empty in case of no validation Errors, * otherwise an array with the structure * [nonvalidField] = text from objText * is being created. * * @return bool * @deprecated */ public function validateForm() { $arrReturn = array(); $arrFieldsToCheck = $this->getRequiredFields(); foreach ($arrFieldsToCheck as $strFieldname => $strType) { //backwards compatibility if ($strType == "string") { $strType = "text"; } //backwards compatibility if ($strType == "number") { $strType = "numeric"; } $strValue = $this->getParam($strFieldname); if ($strType == "date") { $objDate = new \Kajona\System\System\Date("0"); $objDate->generateDateFromParams($strFieldname, $this->getAllParams()); $strValue = $objDate; } $objValidator = $this->getValidatorInstance($strType); if (!$objValidator->validate($strValue)) { if ($this->getLang("required_".$strFieldname) != "!required_".$strFieldname."!") { $arrReturn[$strFieldname] = $this->getLang("required_".$strFieldname); } elseif ($this->getLang($strFieldname) != "!".$strFieldname."!") { $arrReturn[$strFieldname] = $this->getLang($strFieldname); } else { $arrReturn[$strFieldname] = $this->getLang("required_".$strFieldname); } } } $this->arrValidationErrors = array_merge($this->arrValidationErrors, $arrReturn); return (count($this->arrValidationErrors) == 0); } /** * Loads the validator identified by the passed name. * * @param string $strName * * @return ValidatorInterface * @throws Exception * @deprecated */ private function getValidatorInstance($strName) { if (class_exists($strName)) { return new $strName(); } if (uniStrpos($strName, "class_") === false) { $strName = "class_".$strName."_validator"; } if (Resourceloader::getInstance()->getPathForFile("/system/validators/".$strName.".php")) { return new $strName(); } else { throw new Exception("failed to load validator of type ".$strName, Exception::$level_ERROR); } } /** * Loads the data of the current element * * @return mixed */ public final function loadElementData() { $objAnnotations = new Reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(OrmBase::STR_ANNOTATION_TARGETTABLE); $strTargetTable = ""; if (count($arrTargetTables) != 0) { $arrCachedRow = OrmRowcache::getCachedInitRow($this->getSystemid()); if ($arrCachedRow !== null && !isset($arrCachedRow["content_id"])) { OrmRowcache::removeSingleRow($this->getSystemid()); } $objORM = new OrmObjectinit($this); $objORM->initObjectFromDb(); $arrTables = explode(".", $arrTargetTables[0]); $strTargetTable = _dbprefix_.$arrTables[0]; } elseif ($this->getArrModule("table") != "") { $strTargetTable = $this->getArrModule("table"); } $objORM = new OrmObjectlist(); //Element-Table given? if ($strTargetTable != "") { $strQuery = "SELECT * FROM ".$strTargetTable.", "._dbprefix_."element, "._dbprefix_."page_element, "._dbprefix_."system_right, "._dbprefix_."system LEFT JOIN "._dbprefix_."system_date ON (system_id = system_date_id) WHERE element_name = page_element_ph_element AND page_element_id = content_id AND system_id = right_id AND system_id = content_id ".$objORM->getDeletedWhereRestriction()." AND system_id = ? "; } else { $strQuery = "SELECT * FROM "._dbprefix_."element, "._dbprefix_."page_element, "._dbprefix_."system_right, "._dbprefix_."system LEFT JOIN "._dbprefix_."system_date ON (system_id = system_date_id) WHERE element_name = page_element_ph_element AND page_element_id = system_id AND system_id = right_id ".$objORM->getDeletedWhereRestriction()." AND system_id = ? "; } $this->arrElementData = Carrier::getInstance()->getObjDB()->getPRow($strQuery, array($this->getSystemid())); OrmRowcache::addSingleInitRow($this->arrElementData); return $this->arrElementData; } /** * @throws Exception * @return void */ public function updateForeignElement() { $objAnnotations = new Reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(OrmBase::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) != 0) { $objORM = new OrmObjectupdate($this); $objORM->updateStateToDb(); } //legacy code $strElementTableColumns = $this->getArrModule("tableColumns"); if ($strElementTableColumns != "") { //open new tx Carrier::getInstance()->getObjDB()->transactionBegin(); $arrElementParams = $this->getArrParamData(); $arrTableRows = explode(",", $strElementTableColumns); if (count($arrTableRows) > 0) { $arrInserts = array(); $arrParams = array(); foreach ($arrTableRows as $strTableColumnName) { $strColumnValue = ""; if (isset($arrElementParams[$strTableColumnName])) { $strColumnValue = $arrElementParams[$strTableColumnName]; } $arrParams[] = $strColumnValue; $arrInserts[] = " ".Carrier::getInstance()->getObjDB()->encloseColumnName($strTableColumnName)." = ? "; } $strRowUpdates = implode(", ", $arrInserts); $strUpdateQuery = " UPDATE ".$this->getTable()." SET " .$strRowUpdates. " WHERE content_id= ? "; $arrParams[] = $this->getSystemid(); if (!Carrier::getInstance()->getObjDB()->_pQuery($strUpdateQuery, $arrParams)) { Carrier::getInstance()->getObjDB()->transactionRollback(); } else { Carrier::getInstance()->getObjDB()->transactionCommit(); } } else { throw new Exception("Element has invalid tableRows value!!!", Exception::$level_ERROR); } } else { //To remain backwards-compatible: //Call the save-method of the element instead or if the element wants to update its data specially if (method_exists($this, "actionSave") && !$this->actionSave($this->getSystemid())) { throw new Exception("Element returned error saving to database!!!", Exception::$level_ERROR); } } } /** * returns the table used by the element * * @return string */ public function getTable() { $objAnnotations = new Reflection($this); $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(OrmBase::STR_ANNOTATION_TARGETTABLE); if (count($arrTargetTables) != 0) { $arrTable = explode(".", $arrTargetTables[0]); return _dbprefix_.$arrTable[0]; } //legacy code return $this->getArrModule("table"); } /** * The label of the first config-value. * Overwrite this method if the element makes use of a config-value. * The value itself may be read by accessing the instance of PagesPageelement * out of the admin-/portal-element-instance directly. * * @return string */ public function getConfigVal1Name() { return ""; } /** * The label of the second config-value. * Overwrite this method if the element makes use of a config-value. * The value itself may be read by accessing the instance of PagesPageelement * out of the admin-/portal-element-instance directly. * * @return string */ public function getConfigVal2Name() { return ""; } /** * The label of the third config-value. * Overwrite this method if the element makes use of a config-value. * The value itself may be read by accessing the instance of PagesPageelement * out of the admin-/portal-element-instance directly. * * @return string */ public function getConfigVal3Name() { return ""; } /** * Callback method to fill a new element with dummy content. * May be overwritten by extending classes. */ public function generateDummyContent() { //see if we can set a default template $objReflection = new Reflection($this); $arrProperties = $objReflection->getPropertiesWithAnnotation(FormentryTemplate::STR_TEMPLATEDIR_ANNOTATION); foreach ($arrProperties as $strPropertyName => $strValue) { $arrTemplates = Resourceloader::getInstance()->getTemplatesInFolder($strValue); if (count($arrTemplates) > 0) { $strSetter = $objReflection->getSetter($strPropertyName); if($strSetter != null) { $this->{$strSetter}($arrTemplates[0]); } } } } /** * Returns a short description of the saved content * Overwrite if needed * * @return string */ public function getContentTitle() { $objAnnotations = new Reflection($this); $arrProperties = $objAnnotations->getPropertiesWithAnnotation(ElementAdmin::STR_ANNOTATION_ELEMENTCONTENTTITLE); if (count($arrProperties) > 0) { $this->loadElementData(); $arrKeys = array_keys($arrProperties); $strGetter = $objAnnotations->getGetter($arrKeys[0]); if ($strGetter != null) { //explicit casts required? could be relevant, depending on the target column type / database system return $this->{$strGetter}(); } } return ""; } /** * Returns a textual description of the current element, based * on the lang key element_description. * * @return string * @since 3.2.1 */ public function getElementDescription() { $strName = uniSubstr(get_class($this), uniStrlen("class_"), -6);//TODO class name parsing $strDesc = $this->getLang($strName."_description"); if ($strDesc == "!".$strName."_description!") { $strDesc = ""; } return $strDesc; } /** * Overwrite this method, if you want to execute * some special actions right after saving the element to the db, e.g. * cleanup functions. * * @since 3.2.1 * @return void */ public function doAfterSaveToDb() { } /** * Overwrite this method if you want to modify the params to be saved to the * database or run other actions right before the element is saved back to the database. * * @since 3.4.0 * @return void */ public function doBeforeSaveToDb() { } /** * If the form generated should be validated, pass true. This invokes * the internal validation and printing of errors. * By default, the value is false. The framework sets the value, so there's no * need to call this setter in concrete element classes. * * @param bool $bitDoValidation * * @return void */ final public function setDoValidation($bitDoValidation) { $this->bitDoValidation = $bitDoValidation; } /** * Sub-classes can use this method to add content to the system-form. * Elements in the system-form are hidden by default. * Using this form-section is usefull for mostly unused settings. * * @param string $strContent * * @return void * @since 3.3 * * @todo */ final protected function addOptionalFormElement($strContent) { $this->strSystemFormElements .= $strContent; } /** * Returns the array of parameters passed by the request * * @return array */ public function getArrParamData() { return $this->arrParamData; } /** * Sets the array of parameters passed by the request * * @param array $arrParamData * * @return void */ public function setArrParamData($arrParamData) { $this->arrParamData = $arrParamData; } /** * Return an on-lick link for the passed object. * This link is rendered by the portal search result generator, so * make sure the link is a valid portal page. * If you want to suppress the entry from the result, return an empty string instead. * * @param SearchResult $objResult * * @see getLinkPortalHref() * @return mixed */ public function updateSearchResult(SearchResult $objResult) { $objCur = Objectfactory::getInstance()->getObject($this->getSystemid()); while($objCur != null && !$objCur instanceof PagesPage && !$objCur instanceof SystemModule) { $objCur = Objectfactory::getInstance()->getObject($objCur->getStrPrevId()); } if ($objCur instanceof PagesPage && $objCur->getStrName() != 'master') { $objResult->setStrPagelink(Link::getLinkPortal($objCur->getStrName(), "", "_self", $objCur->getStrBrowsername(), "", "&highlight=".urlencode(html_entity_decode($objResult->getObjSearch()->getStrQuery(), ENT_QUOTES, "UTF-8")))); $objResult->setStrPagename($objCur->getStrName()); } } /** * Since the portal may be split in different languages, * return the content lang of the current record using the common * abbreviation such as "de" or "en". * If the content is not assigned to any language, return "" instead (e.g. a single image). * * @return mixed */ public function getContentLang() { $this->loadElementData(); return isset($this->arrElementData["page_element_ph_language"]) ? $this->arrElementData["page_element_ph_language"] : ""; } /** * Return an on-lick link for the passed object. * This link is used by the backend-search for the autocomplete-field * * @see getLinkAdminHref() * @return mixed */ public function getSearchAdminLinkForObject() { //the default, plz return ""; } } |