protected function execute(InputInterface $input, OutputInterface $output) { // display error message if (!$input->getOption("mode")) { $this->writeError("Please specify the mode!"); exit; } $db = \Pimcore\Db::get(); if ($input->getOption("mode") == "optimize") { $tables = $db->fetchAll("SHOW TABLES"); foreach ($tables as $table) { $t = current($table); try { Logger::debug("Running: OPTIMIZE TABLE " . $t); $db->query("OPTIMIZE TABLE " . $t); } catch (\Exception $e) { Logger::error($e); } } } elseif ($input->getOption("mode") == "warmup") { $tables = $db->fetchAll("SHOW TABLES"); foreach ($tables as $table) { $t = current($table); try { Logger::debug("Running: SELECT COUNT(*) FROM {$t}"); $res = $db->fetchOne("SELECT COUNT(*) FROM {$t}"); Logger::debug("Result: " . $res); } catch (\Exception $e) { Logger::error($e); } } } }
/** * @static * @return bool */ public static function stopCrawler() { \Pimcore\Logger::debug('LuceneSearch: forcing frontend crawler stop'); self::setStopLock('frontend', FALSE); self::setCrawlerState('frontend', 'finished', FALSE); return TRUE; }
/** * @param AbstractPlugin $plugin * @param null $stackIndex * @return $this * @throws \Exception */ public function registerPlugin(AbstractPlugin $plugin, $stackIndex = null) { if (false !== array_search($plugin, $this->_plugins, true)) { throw new \Exception('Plugin already registered'); } //installed? if (!$plugin::isInstalled()) { if (is_object($plugin)) { $className = get_class($plugin); Logger::debug("Not registering plugin [ " . $className . " ] because it is not installed"); } else { Logger::debug("Not registering plugin, it is not an object"); } return $this; } $stackIndex = (int) $stackIndex; if ($stackIndex) { if (isset($this->_plugins[$stackIndex])) { throw new \Exception('Plugin with stackIndex "' . $stackIndex . '" already registered'); } $this->_plugins[$stackIndex] = $plugin; } else { $stackIndex = count($this->_plugins); while (isset($this->_plugins[$stackIndex])) { ++$stackIndex; } $this->_plugins[$stackIndex] = $plugin; } ksort($this->_plugins); $plugin->init(); return $this; }
/** * @return \Zend_Db_Adapter_Abstract */ protected function getDb() { if (!$this->db) { // we're using a new mysql connection here to avoid problems with active (nested) transactions Logger::debug("Initialize dedicated MySQL connection for the cache adapter"); $this->db = Db::getConnection(); } return $this->db; }
public function generateSitemap() { $this->prepareSiteMapFolder(); if (!is_null($this->sitemapDir)) { $hosts = $this->getValidHosts(); if (is_array($hosts)) { foreach ($hosts as $hostName) { $query = new \Zend_Search_Lucene_Search_Query_Boolean(); $hostTerm = new \Zend_Search_Lucene_Index_Term($hostName, 'host'); $hostQuery = new \Zend_Search_Lucene_Search_Query_Term($hostTerm); $query->addSubquery($hostQuery, TRUE); $hostTerm = new \Zend_Search_Lucene_Index_Term(TRUE, 'restrictionGroup_default'); $hostQuery = new \Zend_Search_Lucene_Search_Query_Term($hostTerm); $query->addSubquery($hostQuery, TRUE); $hits = $this->index->find($query); $name = str_replace('.', '-', $hostName); $filePath = $this->sitemapDir . '/sitemap-' . $name . '.xml'; $fh = fopen($filePath, 'w'); fwrite($fh, '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n"); fwrite($fh, '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); fwrite($fh, "\r\n"); for ($i = 0; $i < count($hits); $i++) { $url = $hits[$i]->getDocument()->getField('url'); $uri = str_replace(array('?pimcore_outputfilters_disabled=1', '&pimcore_outputfilters_disabled=1'), '', $url->value); fwrite($fh, '<url>' . "\r\n"); fwrite($fh, ' <loc>' . htmlspecialchars($uri, ENT_QUOTES) . '</loc>' . "\r\n"); fwrite($fh, '</url>' . "\r\n"); } fwrite($fh, '</urlset>' . "\r\n"); fclose($fh); } $filePath = $this->sitemapDir . '/sitemap.xml'; $fh = fopen($filePath, 'w'); fwrite($fh, '<?xml version="1.0" encoding="UTF-8"?>' . "\r\n"); fwrite($fh, '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'); fwrite($fh, "\r\n"); foreach ($hosts as $hostName) { $name = str_replace('.', '-', $hostName); //first host must be main domain - see hint in plugin settings $currenthost = $hosts[0]; fwrite($fh, '<sitemap>' . "\r\n"); fwrite($fh, ' <loc>http://' . $currenthost . '/plugin/LuceneSearch/frontend/sitemap/?sitemap=sitemap-' . $name . '.xml' . '</loc>' . "\r\n"); fwrite($fh, '</sitemap>' . "\r\n"); \Pimcore\Logger::debug('LuceneSearch: ' . $hostName . ' for sitemap.xml added.'); } fwrite($fh, '</sitemapindex>' . "\r\n"); fclose($fh); } else { \Pimcore\Logger::debug('LuceneSearch: could not generate sitemaps, did not find any hosts in index.'); } } else { \Pimcore\Logger::emerg('LuceneSearch: Cannot generate sitemap. Sitemap directory [ ' . $this->sitemapDir . ' ] not available/not writeable and cannot be created'); } }
/** * Validates that a transition between requested states can be done on an element * NOTE: DOES NOT VALIDATE FIELDS @see performAction * @param $actionName * @param $newStatus * @param $newState * @return bool */ public function validateAction($actionName, $newState, $newStatus) { $element = $this->element; if (!$this->workflow->isGlobalAction($actionName)) { $availableActions = $this->getAvailableActions(); //check the action is available if (!array_key_exists($actionName, $availableActions)) { $this->error = "Workflow::validateTransition, Action [{$actionName}] not available for element [{$element->getId()}] with status [{$this->getElementStatus()}]"; Logger::debug($this->error); return false; } $actionToTake = $availableActions[$actionName]; if ($this->actionHasTransition($actionToTake)) { //check that the new state is correct for the action taken if (!array_key_exists($newState, $actionToTake['transitionTo'])) { $this->error = "Workflow::validateTransition, State [{$newState}] not a valid transition state for action [{$actionName}] from status [{$this->getElementStatus()}]"; Logger::debug($this->error); return false; } $availableNewStatuses = $actionToTake['transitionTo'][$newState]; //check that the new status is valid for the action taken if (!in_array($newStatus, $availableNewStatuses)) { $this->error = "Workflow::validateTransition, Status [{$newState}] not a valid transition status for action [{$actionName}] from status [{$this->getElementStatus()}]"; Logger::debug($this->error); return false; } } } return true; }
/** * @param $queryStr * @param null $type * @param null $subtype * @param null $classname * @param null $modifiedRange * @param null $createdRange * @param null $userOwner * @param null $userModification * @param bool $countOnly */ protected function createBackendSearchQuery($queryStr, $type = null, $subtype = null, $classname = null, $modifiedRange = null, $createdRange = null, $userOwner = null, $userModification = null, $countOnly = false) { if ($countOnly) { $selectFields = " count(*) as count "; } else { $selectFields = " * "; } $this->backendQuery = "SELECT " . $selectFields . "\n FROM search_backend_data d\n WHERE (d.data like ? OR properties like ? )"; $this->backendQueryParams = ["%{$queryStr}%", "%{$queryStr}%"]; if (!empty($type)) { $this->backendQuery .= " AND maintype = ? "; $this->backendQueryParams[] = $type; } if (!empty($subtype)) { $this->backendQuery .= " AND type = ? "; $this->backendQueryParams[] = $subtype; } if (!empty($classname)) { $this->backendQuery .= " AND subtype = ? "; $this->backendQueryParams[] = $classname; } if (is_array($modifiedRange)) { if ($modifiedRange[0] != null) { $this->backendQuery .= " AND modificationDate >= ? "; $this->backendQueryParams[] = $modifiedRange[0]; } if ($modifiedRange[1] != null) { $this->backendQuery .= " AND modificationDate <= ? "; $this->backendQueryParams[] = $modifiedRange[1]; } } if (is_array($createdRange)) { if ($createdRange[0] != null) { $this->backendQuery .= " AND creationDate >= ? "; $this->backendQueryParams[] = $createdRange[0]; } if ($createdRange[1] != null) { $this->backendQuery .= " AND creationDate <= ? "; $this->backendQueryParams[] = $createdRange[1]; } } if (!empty($userOwner)) { $this->backendQuery .= " AND userOwner = ? "; $this->backendQueryParams[] = $userOwner; } if (!empty($userModification)) { $this->backendQuery .= " AND userModification = ? "; $this->backendQueryParams[] = $userModification; } Logger::debug($this->backendQuery); Logger::debug($this->backendQueryParams); }
/** * @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; }
/** * Write's an item to the cache // don't use the logger inside here * @param $data * @param $key * @param array $tags * @param null $lifetime * @param null $priority * @param bool $force * @return bool|void */ public static function storeToCache($data, $key, $tags = array(), $lifetime = null, $priority = null, $force = false) { if (!self::$enabled) { return; } // don't put anything into the cache, when cache is cleared if (in_array("__CLEAR_ALL__", self::$clearedTagsStack) && !$force) { return; } // do not cache hardlink-wrappers if ($data instanceof Document\Hardlink\Wrapper\WrapperInterface) { return; } // $priority is currently just for sorting the items in self::addToSaveStack() // maybe it will be added to prioritize items for backends with volatile memories // get cache instance if ($cache = self::getInstance()) { //if ($lifetime !== null) { // $cache->setLifetime($lifetime); //} if ($data instanceof Element\ElementInterface) { // check for currupt data if ($data->getId() < 1) { return; } if (isset($data->_fulldump)) { unset($data->_fulldump); } // get dependencies for this element $tags = $data->getCacheTags($tags); $type = get_class($data); \Logger::debug("prepared " . $type . " " . $data->getId() . " for data cache with tags: " . implode(",", $tags)); } // check for cleared tags, only item which are not cleared within the same session are stored to the cache if (is_array($tags)) { foreach ($tags as $t) { if (in_array($t, self::$clearedTagsStack)) { \Logger::debug("Aborted caching for key: " . $key . " because it is in the clear stack"); return; } } } else { $tags = array(); } // always add the key as tag $tags[] = $key; // array_values() because the tags from \Element_Interface and some others are associative eg. array("object_123" => "object_123") $tags = array_values($tags); if (is_object($data) && isset($data->____pimcore_cache_item__)) { unset($data->____pimcore_cache_item__); } $key = self::$cachePrefix . $key; if ($lifetime === null) { $lifetime = false; // set to false otherwise the lifetime stays at null (\Zend_Cache_Backend::getLifetime()) } $success = $cache->save($data, $key, $tags, $lifetime); if ($success !== true) { \Logger::error("Failed to add entry {$key} to the cache, item-size was " . formatBytes(strlen(serialize($data)))); } \Logger::debug("Added " . $key . " to cache"); return $success; } }
/** * Save changes to database, it's an good idea to use save() instead * * @return void */ public function update() { parent::update(); // get fields which shouldn't be updated $fieldDefinitions = $this->model->getClass()->getFieldDefinitions(); $untouchable = []; foreach ($fieldDefinitions as $key => $fd) { if (method_exists($fd, "getLazyLoading") && $fd->getLazyLoading()) { if (!in_array($key, $this->model->getLazyLoadedFields())) { //this is a relation subject to lazy loading - it has not been loaded $untouchable[] = $key; } } } // empty relation table except the untouchable fields (eg. lazy loading fields) if (count($untouchable) > 0) { $untouchables = "'" . implode("','", $untouchable) . "'"; $this->db->delete("object_relations_" . $this->model->getClassId(), $this->db->quoteInto("src_id = ? AND fieldname not in (" . $untouchables . ") AND ownertype = 'object'", $this->model->getId())); } else { $this->db->delete("object_relations_" . $this->model->getClassId(), $this->db->quoteInto("src_id = ? AND ownertype = 'object'", $this->model->getId())); } $inheritedValues = Object\AbstractObject::doGetInheritedValues(); Object\AbstractObject::setGetInheritedValues(false); $data = []; $data["oo_id"] = $this->model->getId(); foreach ($fieldDefinitions as $key => $fd) { $getter = "get" . ucfirst($key); if (method_exists($fd, "save")) { // for fieldtypes which have their own save algorithm eg. fieldcollections, objects, multihref, ... $fd->save($this->model); } elseif ($fd->getColumnType()) { // pimcore saves the values with getDataForResource if (is_array($fd->getColumnType())) { $insertDataArray = $fd->getDataForResource($this->model->{$getter}(), $this->model); if (is_array($insertDataArray)) { $data = array_merge($data, $insertDataArray); } } else { $insertData = $fd->getDataForResource($this->model->{$getter}(), $this->model); $data[$key] = $insertData; } } } $this->db->insertOrUpdate("object_store_" . $this->model->getClassId(), $data); // get data for query table $data = []; $this->inheritanceHelper->resetFieldsToCheck(); $oldData = $this->db->fetchRow("SELECT * FROM object_query_" . $this->model->getClassId() . " WHERE oo_id = ?", $this->model->getId()); $inheritanceEnabled = $this->model->getClass()->getAllowInherit(); $parentData = null; if ($inheritanceEnabled) { // get the next suitable parent for inheritance $parentForInheritance = $this->model->getNextParentForInheritance(); if ($parentForInheritance) { // we don't use the getter (built in functionality to get inherited values) because we need to avoid race conditions // we cannot Object\AbstractObject::setGetInheritedValues(true); and then $this->model->$method(); // so we select the data from the parent object using FOR UPDATE, which causes a lock on this row // so the data of the parent cannot be changed while this transaction is on progress $parentData = $this->db->fetchRow("SELECT * FROM object_query_" . $this->model->getClassId() . " WHERE oo_id = ? FOR UPDATE", $parentForInheritance->getId()); } } foreach ($fieldDefinitions as $key => $fd) { if ($fd->getQueryColumnType()) { //exclude untouchables if value is not an array - this means data has not been loaded if (!(in_array($key, $untouchable) and !is_array($this->model->{$key}))) { $method = "get" . $key; $fieldValue = $this->model->{$method}(); $insertData = $fd->getDataForQueryResource($fieldValue, $this->model); $isEmpty = $fd->isEmpty($fieldValue); if (is_array($insertData)) { $columnNames = array_keys($insertData); $data = array_merge($data, $insertData); } else { $columnNames = [$key]; $data[$key] = $insertData; } // if the current value is empty and we have data from the parent, we just use it if ($isEmpty && $parentData) { foreach ($columnNames as $columnName) { if (array_key_exists($columnName, $parentData)) { $data[$columnName] = $parentData[$columnName]; if (is_array($insertData)) { $insertData[$columnName] = $parentData[$columnName]; } else { $insertData = $parentData[$columnName]; } } } } if ($inheritanceEnabled && $fd->getFieldType() != "calculatedValue") { //get changed fields for inheritance if ($fd->isRelationType()) { if (is_array($insertData)) { $doInsert = false; foreach ($insertData as $insertDataKey => $insertDataValue) { if ($isEmpty && $oldData[$insertDataKey] == $parentData[$insertDataKey]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$insertDataKey] != $insertDataValue) { $doInsert = true; break; } } if ($doInsert) { $this->inheritanceHelper->addRelationToCheck($key, $fd, array_keys($insertData)); } } else { if ($isEmpty && $oldData[$key] == $parentData[$key]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$key] != $insertData) { $this->inheritanceHelper->addRelationToCheck($key, $fd); } } } else { if (is_array($insertData)) { foreach ($insertData as $insertDataKey => $insertDataValue) { if ($isEmpty && $oldData[$insertDataKey] == $parentData[$insertDataKey]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$insertDataKey] != $insertDataValue) { $this->inheritanceHelper->addFieldToCheck($insertDataKey, $fd); } } } else { if ($isEmpty && $oldData[$key] == $parentData[$key]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$key] != $insertData) { // data changed, do check and update $this->inheritanceHelper->addFieldToCheck($key, $fd); } } } } } else { Logger::debug("Excluding untouchable query value for object [ " . $this->model->getId() . " ] key [ {$key} ] because it has not been loaded"); } } } $data["oo_id"] = $this->model->getId(); $this->db->insertOrUpdate("object_query_" . $this->model->getClassId(), $data); Object\AbstractObject::setGetInheritedValues($inheritedValues); }
/** * Hook called when maintenance script is called */ public function maintenanceJob() { if (self::isInstalled()) { $currentHour = date('H', time()); //Frontend recrawl $running = self::frontendCrawlerRunning(); $enabled = Configuration::get('frontend.enabled'); $lastStarted = Configuration::getCoreSetting('started'); $lastFinished = Configuration::getCoreSetting('finished'); $forceStart = Configuration::getCoreSetting('forceStart'); $aDayAgo = time() - 24 * 60 * 60; /** * + If Crawler is enabled * + If Crawler is not running * + If last start of Crawler is initial or a day ago * + If it's between 1 + 3 o clock in the night * + OR if its force * => RUN */ if ($enabled && !$running && ((is_bool($lastStarted) || $lastStarted <= $aDayAgo) && $currentHour > 1 && $currentHour < 3 || $forceStart)) { \Pimcore\Logger::debug('starting frontend recrawl...'); $this->frontendCrawl(); /** * + If Crawler is Running * + If last stop of crawler is before last start * + If last start is older than one day * => We have some errors: EXIT CRAWLING! */ } else { if ($running && $lastFinished < $lastStarted && $lastStarted <= $aDayAgo) { \Pimcore\Logger::error('LuceneSearch: There seems to be a problem with the search crawler! Trying to stop it.'); $this->stopFrontendCrawler(); } } } else { \Pimcore\Logger::debug('LuceneSearch: Plugin is not installed - no maintenance to do for this plugin.'); } }
protected function logEvent($name, GenericEvent $event) { if ($this->debug === TRUE) { \Pimcore\Logger::debug('LuceneSearch [' . $name . ']: ' . $event->getArgument('uri')->toString()); } }
/** * converts object data to a simple string value or CSV Export * @abstract * @param Object\AbstractObject $object * @param array $params * @return string */ public function getForCsvExport($object, $params = []) { Logger::debug("csv not supported"); //TODO }
/** * */ public function maintenanceCleanUp() { $conf["document"] = Config::getSystemConfig()->documents->versions; $conf["asset"] = Config::getSystemConfig()->assets->versions; $conf["object"] = Config::getSystemConfig()->objects->versions; $elementTypes = []; foreach ($conf as $elementType => $tConf) { if (intval($tConf->days) > 0) { $versioningType = "days"; $value = intval($tConf->days); } else { $versioningType = "steps"; $value = intval($tConf->steps); } if ($versioningType) { $elementTypes[] = ["elementType" => $elementType, $versioningType => $value]; } } $ignoredIds = []; while (true) { $versions = $this->getDao()->maintenanceGetOutdatedVersions($elementTypes, $ignoredIds); if (count($versions) == 0) { break; } $counter = 0; Logger::debug("versions to check: " . count($versions)); if (is_array($versions) && !empty($versions)) { $totalCount = count($versions); foreach ($versions as $index => $id) { try { $version = Version::getById($id); } catch (\Exception $e) { $ignoredIds[] = $id; Logger::debug("Version with " . $id . " not found\n"); continue; } $counter++; // do not delete public versions if ($version->getPublic()) { $ignoredIds[] = $version->getId(); continue; } if ($version->getCtype() == "document") { $element = Document::getById($version->getCid()); } elseif ($version->getCtype() == "asset") { $element = Asset::getById($version->getCid()); } elseif ($version->getCtype() == "object") { $element = Object::getById($version->getCid()); } if ($element instanceof ElementInterface) { Logger::debug("currently checking Element-ID: " . $element->getId() . " Element-Type: " . Element\Service::getElementType($element) . " in cycle: " . $counter . "/" . $totalCount); if ($element->getModificationDate() >= $version->getDate()) { // delete version if it is outdated Logger::debug("delete version: " . $version->getId() . " because it is outdated"); $version->delete(); } else { $ignoredIds[] = $version->getId(); Logger::debug("do not delete version (" . $version->getId() . ") because version's date is newer than the actual modification date of the element. Element-ID: " . $element->getId() . " Element-Type: " . Element\Service::getElementType($element)); } } else { // delete version if the corresponding element doesn't exist anymore Logger::debug("delete version (" . $version->getId() . ") because the corresponding element doesn't exist anymore"); $version->delete(); } // call the garbage collector if memory consumption is > 100MB if (memory_get_usage() > 100000000) { \Pimcore::collectGarbage(); } } } } }
/** * Intercept the query end and log the profiling data. * * @param integer $queryId * @throws \Zend_Db_Profiler_Exception * @return void */ public function queryEnd($queryId) { $state = parent::queryEnd($queryId); if (!$this->getEnabled() || $state == self::IGNORED) { return; } $profile = $this->getQueryProfile($queryId); $this->_totalElapsedTime += $profile->getElapsedSecs(); $this->_totalQueries++; $logEntry = $profile->getQuery() . " | " . implode(",", $profile->getQueryParams()); Logger::debug($logEntry, ["connection" => $this->getConnectionId(), "queryNum" => $this->_totalQueries, "time" => (string) round($profile->getElapsedSecs(), 5)]); $this->queries[] = ["time" => $profile->getElapsedSecs(), "query" => $profile->getQuery() . " | " . implode(",", $profile->getQueryParams())]; }
/** * */ public function usageStatistics() { if (Config::getSystemConfig()->general->disableusagestatistics) { return; } $logFile = PIMCORE_LOG_DIRECTORY . "/usagelog.log"; if (is_file($logFile) && filesize($logFile) > 200000) { $data = gzencode(file_get_contents($logFile)); $response = Tool::getHttpData("https://www.pimcore.org/usage-statistics/", [], ["data" => $data]); if (strpos($response, "true") !== false) { @unlink($logFile); Logger::debug("Usage statistics are transmitted and logfile was cleaned"); } else { Logger::debug("Unable to send usage statistics"); } } }
/** * */ public function load() { $model = $this->model; Logger::debug("load called"); $table = $this->getTableName(); $db = \Pimcore\Db::get(); $sql = "SELECT * FROM " . $table . " WHERE o_id = " . $model->getObjectId(); $result = $db->fetchAll($sql); $model->setProperties($result); Logger::debug("result=" . $result); }
/** * Static helper to get a Document by it's path * @param string $path * @return Document|Document\Email|Document\Folder|Document\Hardlink|Document\Link|Document\Page|Document\Printcontainer|Document\Printpage|Document\Snippet */ public static function getByPath($path) { $path = Element\Service::correctPath($path); try { $document = new Document(); // validate path if (Tool::isValidPath($path)) { $document->getDao()->getByPath($path); } return self::getById($document->getId()); } catch (\Exception $e) { Logger::debug($e->getMessage()); } return null; }
/** * @param string $id * @return Unit */ public static function getById($id) { $cacheKey = Unit\Dao::TABLE_NAME . "_" . $id; try { $unit = \Zend_Registry::get($cacheKey); } catch (\Exception $e) { try { $unit = new self(); $unit->getDao()->getById($id); \Zend_Registry::set($cacheKey, $unit); } catch (\Exception $ex) { Logger::debug($ex->getMessage()); return null; } } return $unit; }
/** * @throws \Exception */ public function delete() { $userId = $this->model->getId(); Logger::debug("delete user with ID: " . $userId); try { $this->db->delete("users", $this->db->quoteInto("id = ?", $userId)); } catch (\Exception $e) { throw $e; } }
/** * @param $elementTypes * @return array */ public function maintenanceGetOutdatedVersions($elementTypes, $ignoreIds = []) { $ignoreIdsList = implode(",", $ignoreIds); if (!$ignoreIdsList) { $ignoreIdsList = "0"; // set a default to avoid SQL errors (there's no version with ID 0) } $versionIds = []; Logger::debug("ignore ID's: " . $ignoreIdsList); if (!empty($elementTypes)) { $count = 0; $stop = false; foreach ($elementTypes as $elementType) { if ($elementType["days"] > 0) { // by days $deadline = time() - $elementType["days"] * 86400; $tmpVersionIds = $this->db->fetchCol("SELECT id FROM versions as a WHERE (ctype = ? AND date < ?) AND NOT public AND id NOT IN (" . $ignoreIdsList . ")", [$elementType["elementType"], $deadline]); $versionIds = array_merge($versionIds, $tmpVersionIds); } else { // by steps $elementIds = $this->db->fetchCol("SELECT cid,count(*) as amount FROM versions WHERE ctype = ? AND NOT public AND id NOT IN (" . $ignoreIdsList . ") GROUP BY cid HAVING amount > ?", [$elementType["elementType"], $elementType["steps"]]); foreach ($elementIds as $elementId) { $count++; Logger::info($elementId . "(object " . $count . ") Vcount " . count($versionIds)); $elementVersions = $this->db->fetchCol("SELECT id FROM versions WHERE cid = ? and ctype = ? ORDER BY date DESC LIMIT " . $elementType["steps"] . ",1000000", [$elementId, $elementType["elementType"]]); $versionIds = array_merge($versionIds, $elementVersions); // call the garbage collector if memory consumption is > 100MB if (memory_get_usage() > 100000000 && $count % 100 == 0) { \Pimcore::collectGarbage(); sleep(1); $versionIds = array_unique($versionIds); } if (count($versionIds) > 1000) { $stop = true; break; } } $versionIds = array_unique($versionIds); if ($stop) { break; } } } } Logger::info("return " . count($versionIds) . " ids\n"); return $versionIds; }
/** * @param $key * @param bool $force */ public function lock($key, $force = true) { Logger::debug("Locking: '" . $key . "'"); $updateMethod = $force ? "insertOrUpdate" : "insert"; $this->db->{$updateMethod}("locks", ["id" => $key, "date" => time()]); }
/** * @throws \Exception * @throws \Zend_Db_Adapter_Exception */ public function update() { $class = get_object_vars($this->model); $data = []; foreach ($class as $key => $value) { if (in_array($key, $this->getValidTableColumns("classes"))) { $data[$key] = $value; } } $this->db->update("classes", $data, $this->db->quoteInto("id = ?", $this->model->getId())); $objectTable = "object_query_" . $this->model->getId(); $objectDatastoreTable = "object_store_" . $this->model->getId(); $objectDatastoreTableRelation = "object_relations_" . $this->model->getId(); $objectView = "object_" . $this->model->getId(); // create object table if not exists $protectedColums = ["oo_id", "oo_classId", "oo_className"]; $protectedDatastoreColumns = ["oo_id"]; $this->db->query("CREATE TABLE IF NOT EXISTS `" . $objectTable . "` (\n\t\t\t `oo_id` int(11) NOT NULL default '0',\n\t\t\t `oo_classId` int(11) default '" . $this->model->getId() . "',\n\t\t\t `oo_className` varchar(255) default '" . $this->model->getName() . "',\n\t\t\t PRIMARY KEY (`oo_id`)\n\t\t\t) DEFAULT CHARSET=utf8mb4;"); // update default value of classname columns $this->db->query('ALTER TABLE `' . $objectTable . "` ALTER COLUMN `oo_className` SET DEFAULT '" . $this->model->getName() . "';"); $this->db->query("CREATE TABLE IF NOT EXISTS `" . $objectDatastoreTable . "` (\n\t\t\t `oo_id` int(11) NOT NULL default '0',\n\t\t\t PRIMARY KEY (`oo_id`)\n\t\t\t) DEFAULT CHARSET=utf8mb4;"); $this->db->query("CREATE TABLE IF NOT EXISTS `" . $objectDatastoreTableRelation . "` (\n `src_id` int(11) NOT NULL DEFAULT '0',\n `dest_id` int(11) NOT NULL DEFAULT '0',\n `type` varchar(50) NOT NULL DEFAULT '',\n `fieldname` varchar(70) NOT NULL DEFAULT '0',\n `index` int(11) unsigned NOT NULL DEFAULT '0',\n `ownertype` enum('object','fieldcollection','localizedfield','objectbrick') NOT NULL DEFAULT 'object',\n `ownername` varchar(70) NOT NULL DEFAULT '',\n `position` varchar(70) NOT NULL DEFAULT '0',\n PRIMARY KEY (`src_id`,`dest_id`,`ownertype`,`ownername`,`fieldname`,`type`,`position`),\n KEY `index` (`index`),\n KEY `src_id` (`src_id`),\n KEY `dest_id` (`dest_id`),\n KEY `fieldname` (`fieldname`),\n KEY `position` (`position`),\n KEY `ownertype` (`ownertype`),\n KEY `type` (`type`),\n KEY `ownername` (`ownername`)\n ) DEFAULT CHARSET=utf8mb4;"); $existingColumns = $this->getValidTableColumns($objectTable, false); // no caching of table definition $existingDatastoreColumns = $this->getValidTableColumns($objectDatastoreTable, false); // no caching of table definition $columnsToRemove = $existingColumns; $datastoreColumnsToRemove = $existingDatastoreColumns; Object\ClassDefinition\Service::updateTableDefinitions($this->tableDefinitions, [$objectTable, $objectDatastoreTable]); // add non existing columns in the table if (is_array($this->model->getFieldDefinitions()) && count($this->model->getFieldDefinitions())) { foreach ($this->model->getFieldDefinitions() as $key => $value) { // if a datafield requires more than one column in the query table if (is_array($value->getQueryColumnType())) { foreach ($value->getQueryColumnType() as $fkey => $fvalue) { $this->addModifyColumn($objectTable, $key . "__" . $fkey, $fvalue, "", "NULL"); $protectedColums[] = $key . "__" . $fkey; } } // if a datafield requires more than one column in the datastore table => only for non-relation types if (!$value->isRelationType() && is_array($value->getColumnType())) { foreach ($value->getColumnType() as $fkey => $fvalue) { $this->addModifyColumn($objectDatastoreTable, $key . "__" . $fkey, $fvalue, "", "NULL"); $protectedDatastoreColumns[] = $key . "__" . $fkey; } } // everything else // if (!is_array($value->getQueryColumnType()) && !is_array($value->getColumnType())) { if (!is_array($value->getQueryColumnType()) && $value->getQueryColumnType()) { $this->addModifyColumn($objectTable, $key, $value->getQueryColumnType(), "", "NULL"); $protectedColums[] = $key; } if (!is_array($value->getColumnType()) && $value->getColumnType() && !$value->isRelationType()) { $this->addModifyColumn($objectDatastoreTable, $key, $value->getColumnType(), "", "NULL"); $protectedDatastoreColumns[] = $key; } // } // add indices $this->addIndexToField($value, $objectTable, "getQueryColumnType"); $this->addIndexToField($value, $objectDatastoreTable, "getColumnType"); } } // remove unused columns in the table $this->removeUnusedColumns($objectTable, $columnsToRemove, $protectedColums); $this->removeUnusedColumns($objectDatastoreTable, $datastoreColumnsToRemove, $protectedDatastoreColumns); // remove / cleanup unused relations if (is_array($datastoreColumnsToRemove)) { foreach ($datastoreColumnsToRemove as $value) { if (!in_array(strtolower($value), array_map('strtolower', $protectedDatastoreColumns))) { $tableRelation = "object_relations_" . $this->model->getId(); $this->db->delete($tableRelation, "fieldname = " . $this->db->quote($value) . " AND ownertype = 'object'"); // @TODO: remove localized fields and fieldcollections } } } // create view try { //$this->db->query('CREATE OR REPLACE VIEW `' . $objectView . '` AS SELECT * FROM `objects` left JOIN `' . $objectTable . '` ON `objects`.`o_id` = `' . $objectTable . '`.`oo_id` WHERE `objects`.`o_classId` = ' . $this->model->getId() . ';'); $this->db->query('CREATE OR REPLACE VIEW `' . $objectView . '` AS SELECT * FROM `' . $objectTable . '` JOIN `objects` ON `objects`.`o_id` = `' . $objectTable . '`.`oo_id`;'); } catch (\Exception $e) { Logger::debug($e); } $this->tableDefinitions = null; }
public function importUrlAction() { $success = true; $data = Tool::getHttpData($this->getParam("url")); $filename = basename($this->getParam("url")); $parentId = $this->getParam("id"); $parentAsset = Asset::getById(intval($parentId)); $filename = Element\Service::getValidKey($filename, "asset"); $filename = $this->getSafeFilename($parentAsset->getRealFullPath(), $filename); if (empty($filename)) { throw new \Exception("The filename of the asset is empty"); } // check for duplicate filename $filename = $this->getSafeFilename($parentAsset->getRealFullPath(), $filename); if ($parentAsset->isAllowed("create")) { $asset = Asset::create($parentId, ["filename" => $filename, "data" => $data, "userOwner" => $this->user->getId(), "userModification" => $this->user->getId()]); $success = true; } else { Logger::debug("prevented creating asset because of missing permissions"); } $this->_helper->json(["success" => $success]); }
/** * @param null $page * @param null $path * @return bool|string * @throws \Exception */ public function getText($page = null, $path = null) { $path = $path ? $this->preparePath($path) : $this->path; if ($page || parent::isFileTypeSupported($path)) { // for per page extraction we have to convert the document to PDF and extract the text via ghostscript return parent::getText($page, $this->getPdf($path)); } elseif (File::getFileExtension($path)) { // if we want to get the text of the whole document, we can use libreoffices text export feature $cmd = self::getLibreOfficeCli() . " --headless --nologo --nofirststartwizard --norestore --convert-to txt:Text --outdir " . escapeshellarg(PIMCORE_TEMPORARY_DIRECTORY) . " " . escapeshellarg($path); $out = Console::exec($cmd, null, 240); Logger::debug("LibreOffice Output was: " . $out); $tmpName = PIMCORE_TEMPORARY_DIRECTORY . "/" . preg_replace("/\\." . File::getFileExtension($path) . "\$/", ".txt", basename($path)); if (file_exists($tmpName)) { $text = file_get_contents($tmpName); $text = \Pimcore\Tool\Text::convertToUTF8($text); unlink($tmpName); return $text; } else { $message = "Couldn't convert document to PDF: " . $path . " with the command: '" . $cmd . "' - now trying to get the text out of the PDF ..."; Logger::error($message); return parent::getText(null, $this->getPdf($path)); } } return ""; // default empty string }
protected function waitTillFinished($videoId, $thumbnail) { $finished = false; // initial delay $video = Asset::getById($videoId); $thumb = $video->getThumbnail($thumbnail); if ($thumb["status"] != "finished") { sleep(20); } while (!$finished) { \Pimcore::collectGarbage(); $video = Asset::getById($videoId); $thumb = $video->getThumbnail($thumbnail); if ($thumb["status"] == "finished") { $finished = true; Logger::debug("video [" . $video->getId() . "] FINISHED"); } elseif ($thumb["status"] == "inprogress") { Logger::debug("video [" . $video->getId() . "] in progress ..."); sleep(5); } else { // error Logger::debug("video [" . $video->getId() . "] has status: '" . $thumb["status"] . "' -> skipping"); break; } } }
/** * This method is called in Object\\ClassDefinition::save() and is used to create the database table for the localized data * @param Object\ClassDefinition $class * @param mixed $params * @return void */ public function classSaved($class, $params = []) { // iterate over fieldDefinitions array and check if there is an item of type // object_Class_Data_KeyValue // if found, create the table, otherwise do nothing $keyValue = new Object\Data\KeyValue(); $keyValue->setClass($class); $fieldDefinitions = $class->getFieldDefinitions(); //TODO is this even called if type keyvalue not part of the class def? foreach ($fieldDefinitions as $definition) { if ($definition instanceof Object\ClassDefinition\Data\KeyValue) { Logger::debug("found definition of type keyvalue, create table"); $keyValue->createUpdateTable(); break; } } }
/** * @param Object\Concrete $object * @param array $toDelete * @param array $toAdd * @param string $ownerFieldName * @return void */ protected function processRemoteOwnerRelations($object, $toDelete, $toAdd, $ownerFieldName) { $getter = "get" . ucfirst($ownerFieldName); $setter = "set" . ucfirst($ownerFieldName); foreach ($toDelete as $id) { $owner = Object::getById($id); //TODO: lock ?! if (method_exists($owner, $getter)) { $currentData = $owner->{$getter}(); if (is_array($currentData)) { for ($i = 0; $i < count($currentData); $i++) { if ($currentData[$i]->getId() == $object->getId()) { unset($currentData[$i]); $owner->{$setter}($currentData); $owner->setUserModification($this->getUser()->getId()); $owner->save(); Logger::debug("Saved object id [ " . $owner->getId() . " ] by remote modification through [" . $object->getId() . "], Action: deleted [ " . $object->getId() . " ] from [ {$ownerFieldName}]"); break; } } } } } foreach ($toAdd as $id) { $owner = Object::getById($id); //TODO: lock ?! if (method_exists($owner, $getter)) { $currentData = $owner->{$getter}(); $currentData[] = $object; $owner->{$setter}($currentData); $owner->setUserModification($this->getUser()->getId()); $owner->save(); Logger::debug("Saved object id [ " . $owner->getId() . " ] by remote modification through [" . $object->getId() . "], Action: added [ " . $object->getId() . " ] to [ {$ownerFieldName} ]"); } } }
/** * */ public function save() { $this->delete(false); $object = $this->model->getObject(); $validLanguages = Tool::getValidLanguages(); $context = $this->model->getContext(); if ($context && $context["containerType"] == "fieldcollection") { $containerKey = $context["containerKey"]; $container = Object\Fieldcollection\Definition::getByKey($containerKey); } else { $container = $this->model->getClass(); } $fieldDefinitions = $container->getFielddefinition("localizedfields")->getFielddefinitions(); foreach ($validLanguages as $language) { $inheritedValues = Object\AbstractObject::doGetInheritedValues(); Object\AbstractObject::setGetInheritedValues(false); $insertData = ["ooo_id" => $this->model->getObject()->getId(), "language" => $language]; if ($container instanceof Object\Fieldcollection\Definition) { $insertData["fieldname"] = $context["fieldname"]; $insertData["index"] = $context["index"]; } foreach ($fieldDefinitions as $fd) { if (method_exists($fd, "save")) { // for fieldtypes which have their own save algorithm eg. objects, multihref, ... $context = $this->model->getContext() ? $this->model->getContext() : []; if ($context["containerType"] == "fieldcollection") { $context["subContainerType"] = "localizedfield"; } $childParams = ["context" => $context, "language" => $language]; $fd->save($this->model, $childParams); } else { if (is_array($fd->getColumnType())) { $insertDataArray = $fd->getDataForResource($this->model->getLocalizedValue($fd->getName(), $language, true), $object); $insertData = array_merge($insertData, $insertDataArray); } else { $insertData[$fd->getName()] = $fd->getDataForResource($this->model->getLocalizedValue($fd->getName(), $language, true), $object); } } } $storeTable = $this->getTableName(); $queryTable = $this->getQueryTableName() . "_" . $language; $this->db->insertOrUpdate($storeTable, $insertData); if ($container instanceof Object\ClassDefinition) { // query table $data = []; $data["ooo_id"] = $this->model->getObject()->getId(); $data["language"] = $language; $this->inheritanceHelper = new Object\Concrete\Dao\InheritanceHelper($object->getClassId(), "ooo_id", $storeTable, $queryTable); $this->inheritanceHelper->resetFieldsToCheck(); $sql = "SELECT * FROM " . $queryTable . " WHERE ooo_id = " . $object->getId() . " AND language = '" . $language . "'"; $oldData = []; try { $oldData = $this->db->fetchRow($sql); } catch (\Exception $e) { // if the table doesn't exist -> create it! if (strpos($e->getMessage(), "exist")) { // the following is to ensure consistent data and atomic transactions, while having the flexibility // to add new languages on the fly without saving all classes having localized fields // first we need to roll back all modifications, because otherwise they would be implicitly committed // by the following DDL $this->db->rollBack(); // this creates the missing table $this->createUpdateTable(); // at this point we throw an exception so that the transaction gets repeated in Object::save() throw new \Exception("missing table created, start next run ... ;-)"); } } // get fields which shouldn't be updated $untouchable = []; // @TODO: currently we do not support lazyloading in localized fields $inheritanceEnabled = $object->getClass()->getAllowInherit(); $parentData = null; if ($inheritanceEnabled) { // get the next suitable parent for inheritance $parentForInheritance = $object->getNextParentForInheritance(); if ($parentForInheritance) { // we don't use the getter (built in functionality to get inherited values) because we need to avoid race conditions // we cannot Object\AbstractObject::setGetInheritedValues(true); and then $this->model->getLocalizedValue($key, $language) // so we select the data from the parent object using FOR UPDATE, which causes a lock on this row // so the data of the parent cannot be changed while this transaction is on progress $parentData = $this->db->fetchRow("SELECT * FROM " . $queryTable . " WHERE ooo_id = ? AND language = ? FOR UPDATE", [$parentForInheritance->getId(), $language]); } } foreach ($fieldDefinitions as $fd) { if ($fd->getQueryColumnType()) { $key = $fd->getName(); // exclude untouchables if value is not an array - this means data has not been loaded if (!(in_array($key, $untouchable) and !is_array($this->model->{$key}))) { $localizedValue = $this->model->getLocalizedValue($key, $language); $insertData = $fd->getDataForQueryResource($localizedValue, $object); $isEmpty = $fd->isEmpty($localizedValue); if (is_array($insertData)) { $columnNames = array_keys($insertData); $data = array_merge($data, $insertData); } else { $columnNames = [$key]; $data[$key] = $insertData; } // if the current value is empty and we have data from the parent, we just use it if ($isEmpty && $parentData) { foreach ($columnNames as $columnName) { if (array_key_exists($columnName, $parentData)) { $data[$columnName] = $parentData[$columnName]; if (is_array($insertData)) { $insertData[$columnName] = $parentData[$columnName]; } else { $insertData = $parentData[$columnName]; } } } } if ($inheritanceEnabled && $fd->getFieldType() != "calculatedValue") { //get changed fields for inheritance if ($fd->isRelationType()) { if (is_array($insertData)) { $doInsert = false; foreach ($insertData as $insertDataKey => $insertDataValue) { if ($isEmpty && $oldData[$insertDataKey] == $parentData[$insertDataKey]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$insertDataKey] != $insertDataValue) { $doInsert = true; break; } } if ($doInsert) { $this->inheritanceHelper->addRelationToCheck($key, $fd, array_keys($insertData)); } } else { if ($isEmpty && $oldData[$key] == $parentData[$key]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$key] != $insertData) { $this->inheritanceHelper->addRelationToCheck($key, $fd); } } } else { if (is_array($insertData)) { foreach ($insertData as $insertDataKey => $insertDataValue) { if ($isEmpty && $oldData[$insertDataKey] == $parentData[$insertDataKey]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$insertDataKey] != $insertDataValue) { $this->inheritanceHelper->addFieldToCheck($insertDataKey, $fd); } } } else { if ($isEmpty && $oldData[$key] == $parentData[$key]) { // do nothing, ... value is still empty and parent data is equal to current data in query table } elseif ($oldData[$key] != $insertData) { // data changed, do check and update $this->inheritanceHelper->addFieldToCheck($key, $fd); } } } } } else { Logger::debug("Excluding untouchable query value for object [ " . $this->model->getId() . " ] key [ {$key} ] because it has not been loaded"); } } } $queryTable = $this->getQueryTableName() . "_" . $language; $this->db->insertOrUpdate($queryTable, $data); if ($inheritanceEnabled) { $this->inheritanceHelper->doUpdate($object->getId(), true); } $this->inheritanceHelper->resetFieldsToCheck(); } Object\AbstractObject::setGetInheritedValues($inheritedValues); } // foreach language }
/** * * Checks if an document is an allowed relation * @param Document $document * @return boolean */ protected function allowDocumentRelation($document) { $allowedDocumentTypes = $this->getDocumentTypes(); $allowed = true; if (!$this->getDocumentsAllowed()) { $allowed = false; } elseif ($this->getDocumentsAllowed() and is_array($allowedDocumentTypes) and count($allowedDocumentTypes) > 0) { //check for allowed asset types $allowedTypes = []; foreach ($allowedDocumentTypes as $t) { if ($t['documentTypes']) { $allowedTypes[] = $t['documentTypes']; } } if (!in_array($document->getType(), $allowedTypes) && count($allowedTypes)) { $allowed = false; } } else { //don't check if no allowed document types set } Logger::debug("checked object relation to target document [" . $document->getId() . "] in field [" . $this->getName() . "], allowed:" . $allowed); return $allowed; }