/** * Deletes a single parameter which was set with "setParams" or "setParam" * * @param string | integer $key * @return \Pimcore\Mail Provides fluent interface */ public function unsetParam($key) { if (is_string($key) || is_integer($key)) { unset($this->params[$key]); } else { \Logger::warn('$key has to be a string - unsetParam ignored!'); } return $this; }
public function getChildPermissions($type, $user, $quote = true) { // $parentIds = $this->collectParentIds(); $userIds = $user->getRoles(); $userIds[] = $user->getId(); try { if ($type && $quote) { $type = "`" . $type . "`"; } else { $type = "*"; } $cid = $this->model->getId(); $sql = "SELECT " . $type . " FROM users_workspaces_object WHERE cid != " . $cid . " AND cpath LIKE " . $this->db->quote($this->model->getRealFullPath() . "%") . " AND userId IN (" . implode(",", $userIds) . ") ORDER BY LENGTH(cpath) DESC"; $permissions = $this->db->fetchAll($sql); } catch (\Exception $e) { Logger::warn("Unable to get permission " . $type . " for object " . $this->model->getId()); } return $permissions; }
/** * */ public function save() { try { $this->db->insert("users_permission_definitions", ["key" => $this->model->getKey()]); } catch (\Exception $e) { Logger::warn($e); } }
/** * @param bool $raw * @param bool $writeOnly * @return Wrapper|\Zend_Db_Adapter_Abstract * @throws \Exception * @throws \Zend_Db_Profiler_Exception */ public static function getConnection($raw = false, $writeOnly = false) { // just return the wrapper (for compatibility reasons) // the wrapper itself get's then the connection using $raw = true if (!$raw) { return new Wrapper(); } $charset = "UTF8"; // explicit set charset for connection (to the adapter) $config = Config::getSystemConfig()->database->toArray(); // write only handling if ($writeOnly && isset($config["writeOnly"])) { // overwrite params with write only configuration $config["params"] = $config["writeOnly"]["params"]; } else { if ($writeOnly) { throw new \Exception("writeOnly connection is requested but not configured"); } } $config["params"]["charset"] = $charset; try { $db = \Zend_Db::factory($config["adapter"], $config["params"]); $db->query("SET NAMES " . $charset); } catch (\Exception $e) { \Logger::emerg($e); \Pimcore\Tool::exitWithError("Database Error! See debug.log for details"); } // try to set innodb as default storage-engine try { $db->query("SET storage_engine=InnoDB;"); } catch (\Exception $e) { \Logger::warn($e); } // try to set mysql mode try { $db->query("SET sql_mode = '';"); } catch (\Exception $e) { \Logger::warn($e); } $connectionId = $db->fetchOne("SELECT CONNECTION_ID()"); // enable the db-profiler if the devmode is on and there is no custom profiler set (eg. in system.xml) if (PIMCORE_DEVMODE && !$db->getProfiler()->getEnabled() || array_key_exists("pimcore_log", $_REQUEST) && \Pimcore::inDebugMode()) { $profiler = new \Pimcore\Db\Profiler('All DB Queries'); $profiler->setEnabled(true); $profiler->setConnectionId($connectionId); $db->setProfiler($profiler); } \Logger::debug(get_class($db) . ": Successfully established connection to MySQL-Server, Process-ID: " . $connectionId); return $db; }
/** * Save the document. * * @return Document * @throws \Exception */ public function save() { $isUpdate = false; if ($this->getId()) { $isUpdate = true; \Pimcore::getEventManager()->trigger("document.preUpdate", $this); } else { \Pimcore::getEventManager()->trigger("document.preAdd", $this); } $this->correctPath(); // we wrap the save actions in a loop here, so that we can restart the database transactions in the case it fails // if a transaction fails it gets restarted $maxRetries times, then the exception is thrown out // this is especially useful to avoid problems with deadlocks in multi-threaded environments (forked workers, ...) $maxRetries = 5; for ($retries = 0; $retries < $maxRetries; $retries++) { $this->beginTransaction(); try { // set date $this->setModificationDate(time()); if (!$this->getCreationDate()) { $this->setCreationDate(time()); } if (!$isUpdate) { $this->getDao()->create(); } // get the old path from the database before the update is done $oldPath = null; if ($isUpdate) { $oldPath = $this->getDao()->getCurrentFullPath(); } $this->update(); // if the old path is different from the new path, update all children $updatedChildren = []; if ($oldPath && $oldPath != $this->getRealFullPath()) { $this->getDao()->updateWorkspaces(); $updatedChildren = $this->getDao()->updateChildsPaths($oldPath); } $this->commit(); break; // transaction was successfully completed, so we cancel the loop here -> no restart required } catch (\Exception $e) { try { $this->rollBack(); } catch (\Exception $er) { // PDO adapter throws exceptions if rollback fails Logger::error($er); } // we try to start the transaction $maxRetries times again (deadlocks, ...) if ($retries < $maxRetries - 1) { $run = $retries + 1; $waitTime = 100000; // microseconds Logger::warn("Unable to finish transaction (" . $run . ". run) because of the following reason '" . $e->getMessage() . "'. --> Retrying in " . $waitTime . " microseconds ... (" . ($run + 1) . " of " . $maxRetries . ")"); usleep($waitTime); // wait specified time until we restart the transaction } else { // if the transaction still fail after $maxRetries retries, we throw out the exception throw $e; } } } $additionalTags = []; if (isset($updatedChildren) && is_array($updatedChildren)) { foreach ($updatedChildren as $documentId) { $tag = "document_" . $documentId; $additionalTags[] = $tag; // remove the child also from registry (internal cache) to avoid path inconsistencies during long running scripts, such as CLI \Zend_Registry::set($tag, null); } } $this->clearDependentCache($additionalTags); if ($isUpdate) { \Pimcore::getEventManager()->trigger("document.postUpdate", $this); } else { \Pimcore::getEventManager()->trigger("document.postAdd", $this); } return $this; }
/** * @param $allowedTypes * @return $this */ public function setAllowedTypes($allowedTypes) { if (is_string($allowedTypes)) { $allowedTypes = explode(",", $allowedTypes); } if (is_array($allowedTypes)) { for ($i = 0; $i < count($allowedTypes); $i++) { try { Object\Objectbrick\Definition::getByKey($allowedTypes[$i]); } catch (\Exception $e) { Logger::warn("Removed unknown allowed type [ {$allowedTypes[$i]} ] from allowed types of object brick"); unset($allowedTypes[$i]); } } } $this->allowedTypes = (array) $allowedTypes; $this->allowedTypes = array_values($this->allowedTypes); // get rid of indexed array (.join() doesnt work in JS) return $this; }
/** * @param $cmd * @param null $outputFile * @param null $timeout * @return string */ public static function exec($cmd, $outputFile = null, $timeout = null) { if ($timeout && self::getTimeoutBinary()) { // check if --kill-after flag is supported in timeout if (self::$timeoutKillAfterSupport === null) { $out = self::exec(self::getTimeoutBinary() . " --help"); if (strpos($out, "--kill-after")) { self::$timeoutKillAfterSupport = true; } else { self::$timeoutKillAfterSupport = false; } } $killAfter = ""; if (self::$timeoutKillAfterSupport) { $killAfter = " -k 1m"; } $cmd = self::getTimeoutBinary() . $killAfter . " " . $timeout . "s " . $cmd; } elseif ($timeout) { Logger::warn("timeout binary not found, executing command without timeout"); } if ($outputFile) { $cmd = $cmd . " > " . $outputFile . " 2>&1"; } else { // send stderr to /dev/null otherwise this goes to the apache error log and can fill it up pretty quickly if (self::getSystemEnvironment() != 'windows') { $cmd .= " 2> /dev/null"; } } Logger::debug("Executing command `" . $cmd . "` on the current shell"); $return = shell_exec($cmd); return $return; }
/** * @param Mail $mail * @param SendingParamContainer $sendingContainer */ public static function sendNewsletterDocumentBasedMail(Mail $mail, SendingParamContainer $sendingContainer) { $mailAddress = $sendingContainer->getEmail(); if (!empty($mailAddress)) { $mail->setTo($mailAddress); $mail->sendWithoutRendering(); Logger::info("Sent newsletter to: " . self::obfuscateEmail($mailAddress) . " [" . $mail->getDocument()->getId() . "]"); } else { Logger::warn("No E-Mail Address given - cannot send mail. [" . $mail->getDocument()->getId() . "]"); } }
/** * @return $this * @throws \Exception */ public function save() { $isUpdate = false; if ($this->getId()) { $isUpdate = true; \Pimcore::getEventManager()->trigger("object.preUpdate", $this); } else { \Pimcore::getEventManager()->trigger("object.preAdd", $this); } $this->correctPath(); // we wrap the save actions in a loop here, so that we can restart the database transactions in the case it fails // if a transaction fails it gets restarted $maxRetries times, then the exception is thrown out // this is especially useful to avoid problems with deadlocks in multi-threaded environments (forked workers, ...) $maxRetries = 5; for ($retries = 0; $retries < $maxRetries; $retries++) { // be sure that unpublished objects in relations are saved also in frontend mode, eg. in importers, ... $hideUnpublishedBackup = self::getHideUnpublished(); self::setHideUnpublished(false); $this->beginTransaction(); try { if (!in_array($this->getType(), self::$types)) { throw new \Exception("invalid object type given: [" . $this->getType() . "]"); } if (!$isUpdate) { $this->getDao()->create(); } // get the old path from the database before the update is done $oldPath = null; if ($isUpdate) { $oldPath = $this->getDao()->getCurrentFullPath(); } // if the old path is different from the new path, update all children // we need to do the update of the children's path before $this->update() because the // inheritance helper needs the correct paths of the children in InheritanceHelper::buildTree() $updatedChildren = []; if ($oldPath && $oldPath != $this->getRealFullPath()) { $this->getDao()->updateWorkspaces(); $updatedChildren = $this->getDao()->updateChildsPaths($oldPath); } $this->update(); self::setHideUnpublished($hideUnpublishedBackup); $this->commit(); break; // transaction was successfully completed, so we cancel the loop here -> no restart required } catch (\Exception $e) { try { $this->rollBack(); } catch (\Exception $er) { // PDO adapter throws exceptions if rollback fails Logger::info($er); } if ($e instanceof Model\Element\ValidationException) { throw $e; } // set "HideUnpublished" back to the value it was originally self::setHideUnpublished($hideUnpublishedBackup); // we try to start the transaction $maxRetries times again (deadlocks, ...) if ($retries < $maxRetries - 1) { $run = $retries + 1; $waitTime = 100000; // microseconds Logger::warn("Unable to finish transaction (" . $run . ". run) because of the following reason '" . $e->getMessage() . "'. --> Retrying in " . $waitTime . " microseconds ... (" . ($run + 1) . " of " . $maxRetries . ")"); usleep($waitTime); // wait specified time until we restart the transaction } else { // if the transaction still fail after $maxRetries retries, we throw out the exception Logger::error("Finally giving up restarting the same transaction again and again, last message: " . $e->getMessage()); throw $e; } } } $additionalTags = []; if (isset($updatedChildren) && is_array($updatedChildren)) { foreach ($updatedChildren as $objectId) { $tag = "object_" . $objectId; $additionalTags[] = $tag; // remove the child also from registry (internal cache) to avoid path inconsistencies during long running scripts, such as CLI \Zend_Registry::set($tag, null); } } $this->clearDependentCache($additionalTags); if ($isUpdate) { \Pimcore::getEventManager()->trigger("object.postUpdate", $this); } else { \Pimcore::getEventManager()->trigger("object.postAdd", $this); } return $this; }
protected function doSendMailInSingleMode(Model\Document\Newsletter $document, AddressSourceAdapterInterface $addressAdapter, $sendingId) { $totalCount = $addressAdapter->getTotalRecordCount(); //calculate page size based on total item count - with min page size 3 and max page size 10 $fifth = $totalCount / 5; $limit = $fifth > 10 ? 10 : ($fifth < 3 ? 3 : intval($fifth)); $offset = 0; $hasElements = true; while ($hasElements) { $tmpStore = Model\Tool\TmpStore::get($sendingId); $data = $tmpStore->getData(); Logger::info("Sending newsletter " . $hasElements . " / " . $totalCount . " [" . $document->getId() . "]"); $data['progress'] = round($offset / $totalCount * 100, 2); $tmpStore->setData($data); $tmpStore->update(); $sendingParamContainers = $addressAdapter->getParamsForSingleSending($limit, $offset); foreach ($sendingParamContainers as $sendingParamContainer) { $mail = \Pimcore\Tool\Newsletter::prepareMail($document, $sendingParamContainer); \Pimcore\Tool\Newsletter::sendNewsletterDocumentBasedMail($mail, $sendingParamContainer); if (empty($tmpStore)) { Logger::warn("Sending configuration for sending ID {$sendingId} was deleted. Cancelling sending process."); exit; } } $offset += $limit; $hasElements = count($sendingParamContainers); \Pimcore::collectGarbage(); } }
/** * @param string $name * @return Staticroute */ public static function getByName($name, $siteId = null) { $cacheKey = $name . "~~~" . $siteId; // check if pimcore already knows the id for this $name, if yes just return it if (array_key_exists($cacheKey, self::$nameIdMappingCache)) { return self::getById(self::$nameIdMappingCache[$cacheKey]); } // create a tmp object to obtain the id $route = new self(); try { $route->getDao()->getByName($name, $siteId); } catch (\Exception $e) { Logger::warn($e); return null; } // to have a singleton in a way. like all instances of Element\ElementInterface do also, like Object\AbstractObject if ($route->getId() > 0) { // add it to the mini-per request cache self::$nameIdMappingCache[$cacheKey] = $route->getId(); return self::getById($route->getId()); } }
/** * Checks if the action is allowed. * * @param $type * @param $user * @return bool */ public function isAllowed($type, $user) { // collect properties via parent - ids $parentIds = [1]; $obj = $this->model->getParent(); if ($obj) { while ($obj) { $parentIds[] = $obj->getId(); $obj = $obj->getParent(); } } $parentIds[] = $this->model->getId(); $userIds = $user->getRoles(); $userIds[] = $user->getId(); try { $permissionsParent = $this->db->fetchOne("SELECT `" . $type . "` FROM users_workspaces_document WHERE cid IN (" . implode(",", $parentIds) . ") AND userId IN (" . implode(",", $userIds) . ") ORDER BY LENGTH(cpath) DESC, ABS(userId-" . $user->getId() . ") ASC LIMIT 1"); if ($permissionsParent) { return true; } // exception for list permission if (empty($permissionsParent) && $type == "list") { // check for childs with permissions $path = $this->model->getRealFullPath() . "/"; if ($this->model->getId() == 1) { $path = "/"; } $permissionsChilds = $this->db->fetchOne("SELECT list FROM users_workspaces_document WHERE cpath LIKE ? AND userId IN (" . implode(",", $userIds) . ") AND list = 1 LIMIT 1", $path . "%"); if ($permissionsChilds) { return true; } } } catch (\Exception $e) { Logger::warn("Unable to get permission " . $type . " for document " . $this->model->getId()); } return false; }
/** * @return $this */ public function setColorspaceToRGB() { $imageColorspace = $this->resource->getImageColorspace(); if ($imageColorspace == \Imagick::COLORSPACE_CMYK) { if (self::getCMYKColorProfile() && self::getRGBColorProfile()) { $profiles = $this->resource->getImageProfiles('*', false); // we're only interested if ICC profile(s) exist $has_icc_profile = array_search('icc', $profiles) !== false; // if it doesn't have a CMYK ICC profile, we add one if ($has_icc_profile === false) { $this->resource->profileImage('icc', self::getCMYKColorProfile()); } // then we add an RGB profile $this->resource->profileImage('icc', self::getRGBColorProfile()); $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB); // we have to use SRGB here, no clue why but it works } else { $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB); } } elseif ($imageColorspace == \Imagick::COLORSPACE_GRAY) { $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB); } elseif (!in_array($imageColorspace, [\Imagick::COLORSPACE_RGB, \Imagick::COLORSPACE_SRGB])) { $this->resource->setImageColorspace(\Imagick::COLORSPACE_SRGB); } else { // this is to handle embedded icc profiles in the RGB/sRGB colorspace $profiles = $this->resource->getImageProfiles('*', false); $has_icc_profile = array_search('icc', $profiles) !== false; if ($has_icc_profile) { try { // if getImageColorspace() says SRGB but the embedded icc profile is CMYK profileImage() will throw an exception $this->resource->profileImage('icc', self::getRGBColorProfile()); } catch (\Exception $e) { Logger::warn($e); } } } // this is a HACK to force grayscale images to be real RGB - truecolor, this is important if you want to use // thumbnails in PDF's because they do not support "real" grayscale JPEGs or PNGs // problem is described here: http://imagemagick.org/Usage/basics/#type // and here: http://www.imagemagick.org/discourse-server/viewtopic.php?f=2&t=6888#p31891 $currentLocale = setlocale(LC_ALL, "0"); // this locale hack thing is also a hack for imagick setlocale(LC_ALL, "en"); // Set locale to "en" for ImagickDraw::point() to ensure the involved tostring() methods keep the decimal point $draw = new \ImagickDraw(); $draw->setFillColor("#ff0000"); $draw->setfillopacity(0.01); $draw->point(floor($this->getWidth() / 2), floor($this->getHeight() / 2)); // place it in the middle of the image $this->resource->drawImage($draw); setlocale(LC_ALL, $currentLocale); // see setlocale() above, for details ;-) return $this; }
/** * Returns the host URL * * @param string $useProtocol use a specific protocol * * @return string */ public static function getHostUrl($useProtocol = null) { $protocol = self::getRequestScheme(); $port = ''; if (isset($_SERVER["SERVER_PORT"])) { if (!in_array((int) $_SERVER["SERVER_PORT"], [443, 80])) { $port = ":" . $_SERVER["SERVER_PORT"]; } } $hostname = self::getHostname(); //get it from System settings if (!$hostname) { $systemConfig = Config::getSystemConfig()->toArray(); $hostname = $systemConfig['general']['domain']; if (!$hostname) { \Logger::warn('Couldn\'t determine HTTP Host. No Domain set in "Settings" -> "System" -> "Website" -> "Domain"'); return ""; } } if ($useProtocol) { $protocol = $useProtocol; } return $protocol . "://" . $hostname . $port; }
/** * @param array $urlOptions * @param null $name * @param bool $reset * @param bool $encode * @return string|void * @throws \Exception */ public function url(array $urlOptions = [], $name = null, $reset = false, $encode = true) { if (!$urlOptions) { $urlOptions = []; } // when using $name = false we don't use the default route (happens when $name = null / ZF default behavior) // but just the query string generation using the given parameters // eg. $this->url(["foo" => "bar"], false) => /?foo=bar if ($name === null) { if (Staticroute::getCurrentRoute() instanceof Staticroute) { $name = Staticroute::getCurrentRoute()->getName(); } } $siteId = null; if (Site::isSiteRequest()) { $siteId = Site::getCurrentSite()->getId(); } // check for a site in the options, if valid remove it from the options $hostname = null; if (isset($urlOptions["site"])) { $config = Config::getSystemConfig(); $site = $urlOptions["site"]; if (!empty($site)) { try { $site = Site::getBy($site); unset($urlOptions["site"]); $hostname = $site->getMainDomain(); $siteId = $site->getId(); } catch (\Exception $e) { Logger::warn("passed site doesn't exists"); Logger::warn($e); } } elseif ($config->general->domain) { $hostname = $config->general->domain; } } if ($name && ($route = Staticroute::getByName($name, $siteId))) { // assemble the route / url in Staticroute::assemble() $url = $route->assemble($urlOptions, $reset, $encode); // if there's a site, prepend the host to the generated URL if ($hostname && !preg_match("/^https?:/i", $url)) { $url = "//" . $hostname . $url; } return $url; } // this is to add support for arrays as values for the default \Zend_View_Helper_Url $unset = []; foreach ($urlOptions as $optionName => $optionValues) { if (is_array($optionValues)) { foreach ($optionValues as $key => $value) { $urlOptions[$optionName . "[" . $key . "]"] = $value; } $unset[] = $optionName; } } foreach ($unset as $optionName) { unset($urlOptions[$optionName]); } try { return parent::url($urlOptions, $name, $reset, $encode); } catch (\Exception $e) { if (Tool::isFrontentRequestByAdmin()) { // routes can be site specific, so in editmode it's possible that we don't get // the right route (sites are not registered in editmode), so we cannot throw exceptions there return "ERROR_IN_YOUR_URL_CONFIGURATION:~ROUTE--" . $name . "--DOES_NOT_EXIST"; } throw new \Exception("Route '" . $name . "' for building the URL not found"); } }
/** * Returns the host URL * * @param string $useProtocol use a specific protocol * * @return string */ public static function getHostUrl($useProtocol = null) { $protocol = "http"; $port = ''; if (isset($_SERVER["SERVER_PROTOCOL"])) { $protocol = strtolower($_SERVER["SERVER_PROTOCOL"]); $protocol = substr($protocol, 0, strpos($protocol, "/")); $protocol .= isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on" ? "s" : ""; } if (isset($_SERVER["SERVER_PORT"])) { if (!in_array((int) $_SERVER["SERVER_PORT"], array(443, 80))) { $port = ":" . $_SERVER["SERVER_PORT"]; } } $hostname = self::getHostname(); //get it from System settings if (!$hostname) { $systemConfig = Config::getSystemConfig()->toArray(); $hostname = $systemConfig['general']['domain']; if (!$hostname) { \Logger::warn('Couldn\'t determine HTTP Host. No Domain set in "Settings" -> "System" -> "Website" -> "Domain"'); return ""; } } if ($useProtocol) { $protocol = $useProtocol; } return $protocol . "://" . $hostname . $port; }
public function updateCurrentUserAction() { $this->protectCSRF(); $user = $this->getUser(); if ($user != null) { if ($user->getId() == $this->getParam("id")) { $values = \Zend_Json::decode($this->getParam("data")); unset($values["name"]); unset($values["id"]); unset($values["admin"]); unset($values["permissions"]); unset($values["roles"]); unset($values["active"]); if (!empty($values["new_password"])) { $oldPasswordCheck = false; if (empty($values["old_password"])) { // if the user want to reset the password, the old password isn't required $oldPasswordCheck = Tool\Session::useSession(function ($adminSession) use($oldPasswordCheck) { if ($adminSession->password_reset) { return true; } return false; }); } else { // the password has to match $checkUser = Tool\Authentication::authenticatePlaintext($user->getName(), $values["old_password"]); if ($checkUser) { $oldPasswordCheck = true; } } if ($oldPasswordCheck && $values["new_password"] == $values["retype_password"]) { $values["password"] = Tool\Authentication::getPasswordHash($user->getName(), $values["new_password"]); } else { $this->_helper->json(["success" => false, "message" => "password_cannot_be_changed"]); } } $user->setValues($values); $user->save(); $this->_helper->json(["success" => true]); } else { Logger::warn("prevented save current user, because ids do not match. "); $this->_helper->json(false); } } else { $this->_helper->json(false); } }
/** * Updates and save the email log entry to the db and the file-system */ protected function update() { $this->getDao()->update(); if (!is_dir(PIMCORE_LOG_MAIL_PERMANENT)) { File::mkdir(PIMCORE_LOG_MAIL_PERMANENT); } if ($html = $this->getBodyHtml()) { if (File::put(PIMCORE_LOG_MAIL_PERMANENT . '/email-' . $this->getId() . '-html.log', $html) === false) { Logger::warn('Could not write html email log file. LogId: ' . $this->getId()); } } if ($text = $this->getBodyText()) { if (File::put(PIMCORE_LOG_MAIL_PERMANENT . '/email-' . $this->getId() . '-text.log', $text) === false) { Logger::warn('Could not write text email log file. LogId: ' . $this->getId()); } } }
/** See marshal * @param mixed $value * @param Model\Object\AbstractObject $object * @param mixed $params * @return mixed */ public function unmarshal($value, $object = null, $params = []) { $lf = new Object\Localizedfield(); if (is_array($value)) { $items = []; foreach ($value as $language => $languageData) { $languageResult = []; foreach ($languageData as $elementName => $elementData) { $fd = $this->getFielddefinition($elementName); if (!$fd) { // class definition seems to have changed Logger::warn("class definition seems to have changed, element name: " . $elementName); continue; } $dataFromResource = $fd->unmarshal($elementData, $object, ["raw" => true]); $languageResult[$elementName] = $dataFromResource; } $items[$language] = $languageResult; } $lf->setItems($items); } return $lf; }
/** * Creates the Placeholder objects and replaces the placeholder string * with the rendered content of the placeholder object * * @param array $placeholderStack * @return string */ protected function replacePlaceholdersFromStack($placeholderStack = []) { $stringReplaced = null; if (!empty($placeholderStack)) { foreach ($placeholderStack as $placeholder) { $placeholderObject = null; $placeholderClassPrefixes = self::getPlaceholderClassPrefixes(); $placeholderObject = null; foreach ($placeholderClassPrefixes as $classPrefix) { $className = $classPrefix . $placeholder['placeholderClass']; if (Tool::classExists($className)) { $placeholderObject = new $className(); break; } } if (is_null($stringReplaced)) { $stringReplaced = $placeholder['contentString']; } if ($placeholderObject instanceof Placeholder\AbstractPlaceholder) { //setting values from placeholder stack to placeholder objects foreach (array_keys($placeholder) as $key) { if ($key == 'placeholderClass') { continue; } $placeholderObject->{'set' . ucfirst($key)}($placeholder[$key]); } $placeholderObject->setLocale(); $replaceWith = $placeholderObject->getReplacement(); if (!isset($replaceWith)) { $replaceWith = $placeholderObject->getEmptyValue(); } $stringReplaced = str_replace($placeholderObject->getPlaceholderString(), $replaceWith, $stringReplaced); } else { Logger::warn('Ignoring Placeholder "' . $placeholder['placeholderClass'] . '" -> Class not Found or not an instance of Pimcore_Placeholder_Abstract!'); } } } return $stringReplaced; }
/** * This is a dummy and is mostly implemented by relation types * * @param mixed $data * @param array $tags * @return array */ public function getCacheTags($data, $tags = []) { $tags = is_array($tags) ? $tags : []; if (!is_array($data)) { return $tags; } foreach ($data as $blockElements) { foreach ($blockElements as $elementName => $blockElement) { $fd = $this->getFielddefinition($elementName); if (!$fd) { // class definition seems to have changed Logger::warn("class definition seems to have changed, element name: " . $elementName); continue; } $data = $blockElement->getData(); $tags = $fd->getCacheTags($data, $tags); } } return $tags; }