<?php // cache & synchronise class class synccache { var $cachePath; var $showReport; var $deletedfiles = array(); var $aliases = array(); var $parents = array(); var $target; var $config = array(); var $cacheRefreshTime; function synccache() { if(empty($this->target)) $this->target = 'pagecache,sitecache'; if(defined('MODX_BASE_PATH')) $this->cachePath = MODX_BASE_PATH . 'assets/cache/'; } function setTarget($target) { $this->target = $target; } function setCachepath($path) { $this->cachePath = rtrim($path,'/') . '/'; } function setReport($bool) { $this->showReport = $bool; } function escapeDoubleQuotes($s) { $q1 = array("\\","\"","\r","\n","\$"); $q2 = array("\\\\","\\\"","\\r","\\n","\\$"); return str_replace($q1,$q2,$s); } function escapeSingleQuotes($s) { $q1 = array("\\","'"); $q2 = array("\\\\","\\'"); return str_replace($q1,$q2,$s); } function getParents($id, $path = '') { // modx:returns child's parent global $modx; if(empty($this->aliases)) { $fields = "id, IF(alias='', id, alias) AS alias, parent"; $qh = $modx->db->select($fields,'[+prefix+]site_content'); if ($qh && $modx->db->getRecordCount($qh) > 0) { while ($row = $modx->db->getRow($qh)) { $this->aliases[$row['id']] = $row['alias']; $this->parents[$row['id']] = $row['parent']; } } } if (isset($this->aliases[$id])) { if($path !== '') { $path = $this->aliases[$id] . '/' . $path; } else $path = $this->aliases[$id]; return $this->getParents($this->parents[$id], $path); } return $path; } function emptyCache($modx = null) { $instance_name = ''; if(is_object($modx)) { $instance_name = get_class($modx); } $instance_name = strtolower($instance_name); if($instance_name!=='documentparser') global $modx; if(!isset($this->cachePath)) exit('Cache path not set.'); if(strpos($this->target,'pagecache')!==false) $result = $this->emptyPageCache('pageCache'); if(strpos($this->target,'sitecache')!==false) $this->buildCache($modx); $this->publish_time_file($modx); if(isset($result) && $this->showReport==true) $this->showReport($result); } function emptyPageCache($target) { $filesincache = 0; $deletedfilesincache = 0; $pattern = realpath($this->cachePath)."/*.{$target}.php"; $pattern = str_replace('\\','/',$pattern); $files = glob($pattern,GLOB_NOCHECK); $filesincache = ($files['0'] !== $pattern) ? count($files) : 0; $deletedfiles = array(); if(is_array($files) && 0 < $filesincache) { while ($file = array_shift($files)) { $name = basename($file); if (strpos($name,".{$target}")!==false && !in_array($name, $deletedfiles)) { $deletedfilesincache++; $deletedfiles[] = $name; unlink($file); } } } return array($filesincache,$deletedfilesincache,$deletedfiles); } function showReport($info) { list($filesincache,$deletedfilesincache,$deletedfiles) = $info; // finished cache stuff. global $_lang; printf($_lang['refresh_cache'], $filesincache, $deletedfilesincache); $limit = count($deletedfiles); if($limit > 0) { echo '<p>'.$_lang['cache_files_deleted'].'</p><ul>'; for($i=0;$i<$limit; $i++) { echo '<li>',$deletedfiles[$i],'</li>'; } echo '</ul>'; } } /****************************************************************************/ /* PUBLISH TIME FILE */ /****************************************************************************/ function publish_time_file($modx) { global $site_sessionname; // update publish time file $timesArr = array(); $current_time = time(); $result = $modx->db->select('MIN(pub_date) AS minpub','[+prefix+]site_content', "{$current_time} < pub_date"); if(!$result) { echo "Couldn't determine next publish event!"; } $minpub = $modx->db->getValue($result); if($minpub!=NULL) { $timesArr[] = $minpub; } $result = $modx->db->select('MIN(unpub_date) AS minunpub','[+prefix+]site_content', "{$current_time} < unpub_date"); if(!$result) { echo "Couldn't determine next unpublish event!"; } $minunpub = $modx->db->getValue($result); if($minunpub!=NULL) { $timesArr[] = $minunpub; } $result = $modx->db->select('MIN(pub_date) AS minpub','[+prefix+]site_htmlsnippets', "{$current_time} < pub_date"); if(!$result) { echo "Couldn't determine next publish event!"; } $minpub = $modx->db->getValue($result); if($minpub!=NULL) { $timesArr[] = $minpub; } $result = $modx->db->select('MIN(unpub_date) AS minunpub','[+prefix+]site_htmlsnippets', "{$current_time} < unpub_date"); if(!$result) { echo "Couldn't determine next unpublish event!"; } $minunpub = $modx->db->getValue($result); if($minunpub!=NULL) { $timesArr[] = $minunpub; } if(isset($this->cacheRefreshTime) && !empty($this->cacheRefreshTime)) { $timesArr[] = $this->cacheRefreshTime; } if(count($timesArr)>0) $nextevent = min($timesArr); else $nextevent = 0; $rs = $modx->db->select('setting_name,setting_value','[+prefix+]system_settings'); while($row = $modx->db->getRow($rs)) { $name = $row['setting_name']; $value = $row['setting_value']; $setting[$name] = $value; } // write the file $cache_path = $this->cachePath . 'sitePublishing.idx.php'; $content = "<?php\n\$cacheRefreshTime = {$nextevent};\n"; $content .= '$cache_type = ' . "{$setting['cache_type']};\n"; if(isset($site_sessionname) && !empty($site_sessionname)) { $content .= '$site_sessionname = ' . "'{$site_sessionname}';\n"; } $content .= '$site_status = ' . "'{$setting['site_status']}';\n"; $content .= '$error_reporting = ' . "'{$setting['error_reporting']}';\n"; if(isset($setting['site_url']) && !empty($setting['site_url'])) { $content .= '$site_url = ' . "'{$setting['site_url']}';\n"; } if(isset($setting['base_url']) && !empty($setting['base_url'])) { $content .= '$base_url = ' . "'{$setting['base_url']}';\n"; } $rs = file_put_contents($cache_path, $content, LOCK_EX); if (!$rs) exit("Cannot open file ({$filename})"); } /** * build siteCache file * @param DocumentParser $modx * @return boolean success */ function buildCache($modx) { $content = "<?php\n"; $content .= "if(!defined('MODX_BASE_PATH') || strpos(str_replace('\\\\','/',__FILE__), MODX_BASE_PATH)!==0) exit;\n"; // SETTINGS & DOCUMENT LISTINGS CACHE $this->_get_settings($modx); // get settings $this->_get_aliases($modx); // get aliases modx: support for alias path $content .= $this->_get_content_types($modx); // get content types $this->_get_chunks($modx); // WRITE Chunks to cache file $this->_get_snippets($modx); // WRITE snippets to cache file $this->_get_plugins($modx); // WRITE plugins to cache file $content .= $this->_get_events($modx); // WRITE system event triggers // close and write the file $content .= "\n"; $content = str_replace(array("\x0d\x0a", "\x0a", "\x0d"), "\x0a", $content); // invoke OnBeforeCacheUpdate event if ($modx) $modx->invokeEvent('OnBeforeCacheUpdate'); if(!file_put_contents($this->cachePath .'siteCache.idx.php', $content, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } $str = "<?php\n" . 'return ' . var_export($this->config, true) . ';'; if(!file_put_contents($this->cachePath .'config.siteCache.idx.php', $str, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } $str = "<?php\n" . 'return ' . var_export($modx->aliasListing, true) . ';'; if(!file_put_contents($this->cachePath .'aliasListing.siteCache.idx.php', $str, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } $str = "<?php\n" . 'return ' . var_export($modx->documentMap, true) . ';'; if(!file_put_contents($this->cachePath .'documentMap.siteCache.idx.php', $str, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } $str = "<?php\n" . 'return ' . var_export($modx->chunkCache,true) . ';'; if(!file_put_contents($this->cachePath .'chunk.siteCache.idx.php', $str, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } $str = "<?php\n" . 'return ' . var_export($modx->snippetCache, true). ';'; if(!file_put_contents($this->cachePath .'snippet.siteCache.idx.php', $str, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } $str = "<?php\n" . 'return ' . var_export($modx->pluginCache, 'true') . ';'; if(!file_put_contents($this->cachePath .'plugin.siteCache.idx.php', $str, LOCK_EX)) { exit("Cannot write main MODX cache file! Make sure the '{$this->cachePath}' directory is writable!"); } if(!is_file($this->cachePath . '.htaccess')) { file_put_contents($this->cachePath . '.htaccess', "order deny,allow\ndeny from all\n"); } // invoke OnCacheUpdate event if ($modx) $modx->invokeEvent('OnCacheUpdate'); return true; } function _get_settings($modx) { $rs = $modx->db->select('setting_name,setting_value','[+prefix+]system_settings'); $row = array(); while($row = $modx->db->getRow($rs)) { $setting_name = $row['setting_name']; $setting_value = $row['setting_value']; $this->config[$setting_name] = $setting_value; } } function _get_aliases($modx) { $friendly_urls = $modx->db->getValue($modx->db->select('setting_value','[+prefix+]system_settings',"setting_name='friendly_urls'")); if($friendly_urls==1) { $use_alias_path = $modx->db->getValue($modx->db->select('setting_value','[+prefix+]system_settings',"setting_name='use_alias_path'")); } $fields = "IF(alias='', id, alias) AS alias, id, parent, isfolder"; $rs = $modx->db->select($fields,'[+prefix+]site_content','deleted=0','parent, menuindex'); $row = array(); $path = ''; while ($row = $modx->db->getRow($rs)) { if ($friendly_urls == 1 && $use_alias_path == 1) { $path = $this->getParents($row['parent']); } else { $path = $row['parent']; } $alias = $modx->db->escape($row['alias']); $docid = $row['id']; $path = $modx->db->escape($path); $parent = $row['parent']; $isfolder = $row['isfolder']; $modx->aliasListing[$docid] = array('id' => $docid, 'alias' => $alias, 'path' => $path, 'parent' => $parent, 'isfolder' => $isfolder); $modx->documentMap[] = array($parent => $docid); } } function _get_content_types($modx) { $rs = $modx->db->select('id, contentType','[+prefix+]site_content',"contentType != 'text/html'"); $tmpPHP = '$c = &$this->contentTypes;' . "\n"; $row = array(); while ($row = $modx->db->getRow($rs)) { $tmpPHP .= '$c['.$row['id'].']'." = '".$row['contentType']."';\n"; } return $tmpPHP; } function _get_chunks($modx) { $rs = $modx->db->select('name,snippet','[+prefix+]site_htmlsnippets', "`published`='1'"); $row = array(); while ($row = $modx->db->getRow($rs)) { $name = $modx->db->escape($row['name']); $modx->chunkCache[$name] = $row['snippet']; } } function _get_snippets($modx) { $fields = 'ss.name,ss.snippet,ss.properties,sm.properties as `sharedproperties`'; $from = "[+prefix+]site_snippets ss LEFT JOIN [+prefix+]site_modules sm on sm.guid=ss.moduleguid"; $rs = $modx->db->select($fields,$from); $row = array(); while ($row = $modx->db->getRow($rs)) { $name = $row['name']; $snippet = $row['snippet']; $modx->snippetCache[$name] = $snippet; if ($row['properties'] != '' || $row['sharedproperties'] != '') { $properties = $row['properties'] . ' ' . $row['sharedproperties']; $modx->snippetCache["{$name}Props"] = $properties; } } } function _get_plugins($modx) { $fields = 'sp.name,sp.plugincode,sp.properties,sm.properties as `sharedproperties`'; $from = "[+prefix+]site_plugins sp LEFT JOIN [+prefix+]site_modules sm on sm.guid=sp.moduleguid"; $rs = $modx->db->select($fields,$from,'sp.disabled=0'); $row = array(); while ($row = $modx->db->getRow($rs)) { $name = $modx->db->escape($row['name']); $plugincode = $row['plugincode']; $properties = $row['properties'].' '.$row['sharedproperties']; $modx->pluginCache[$name] = $plugincode; if ($row['properties']!='' || $row['sharedproperties']!='') { $modx->pluginCache["{$name}Props"] = $properties; } } } function _get_events($modx) { $fields = 'sysevt.name as `evtname`, plugs.name'; $from = "[+prefix+]system_eventnames sysevt INNER JOIN [+prefix+]site_plugin_events pe ON pe.evtid = sysevt.id INNER JOIN [+prefix+]site_plugins plugs ON plugs.id = pe.pluginid"; $where = 'plugs.disabled=0'; $orderby = 'sysevt.name,pe.priority'; $rs = $modx->db->select($fields,$from,$where,$orderby); $tmpPHP = '$e = &$this->pluginEvent;' . "\n"; $events = array(); $row = array(); while ($row = $modx->db->getRow($rs)) { if(!$events[$row['evtname']]) { $events[$row['evtname']] = array(); } $events[$row['evtname']][] = $row['name']; } foreach($events as $evtname => $pluginnames) { $tmpPHP .= '$e[\''.$evtname.'\'] = array(\''.implode("','",$this->escapeSingleQuotes($pluginnames))."');\n"; } return $tmpPHP; } function tableOpt() { global $modx; $modx->db->optimize('[+prefix+]site_content'); $modx->db->optimize('[+prefix+]active_users'); $modx->db->optimize('[+prefix+]manager_log'); $modx->db->optimize('[+prefix+]event_log'); $modx->db->optimize('[+prefix+]site_htmlsnippets'); } }