PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/BaseModule.php

https://github.com/rasstroen/ljrate
PHP | 250 lines | 187 code | 32 blank | 31 comment | 32 complexity | edf6046dbb74beea56b59ed38932c11f MD5 | raw file
  1. <?php
  2. // проверяем настройки модуля,
  3. // если кеш включен
  4. class BaseModule {
  5. public $xmlPart = false;
  6. protected $moduleName = '';
  7. protected $settings = array();
  8. protected $xml_cache_name = '';
  9. protected $data = array(); // выходные данные модуля
  10. protected $cached = false;
  11. protected $cache_enabled = false;
  12. protected $cachetype = false;
  13. protected $current_view = false; // вьюшка. имямодуля_вьюшка.xsl
  14. protected $props;
  15. protected $writeParameters = array();
  16. private $xHTMLCachingEnabled = false; // модуль можно в виде xHTML положить в кеш
  17. function __construct($moduleName, array $additionalSettings) {
  18. global $dev_mode;
  19. $this->moduleName = $moduleName;
  20. foreach (LibModules::$modules[$moduleName]['params'] as $settingName => $value) {
  21. $this->settings[$settingName] = $value;
  22. }
  23. foreach ($additionalSettings as $settingName => $value) {
  24. // именно на этой странице у модуля появились дополнительные настройки
  25. $this->settings[$settingName] = $value;
  26. }
  27. $this->props = LibModules::$modules[$moduleName];
  28. // вьюшка по умолчанию - первая из списка вьюшек
  29. if (isset($this->props['views'])) {
  30. $this->setCurrentView(array_shift($this->props['views']));
  31. }
  32. $this->props['block'] = $this->settings['block'];
  33. unset($this->settings['block']);
  34. // цепляем данные из соответствующего модуля записи
  35. $this->writeParameters = PostWrite::getWriteParameters($moduleName);
  36. foreach ($this->writeParameters as $f => $v) {
  37. $this->data[$f] = $v;
  38. }
  39. if (isset($this->writeParameters['cache']) && $this->writeParameters['cache'] == false) {
  40. $this->dropCache();
  41. }
  42. if (count($this->writeParameters)) {
  43. $this->disableCaching();
  44. Log::logHtml('caching for module # ' . $moduleName . ' disabled [post params]');
  45. } else
  46. // будем ли использовать кэш для хранения xml результата работы скрипта?
  47. if ($this->checkCacheSettings()) {
  48. // вынимаем из кеша
  49. $cachedXml = $this->getFromCache();
  50. // если получилось
  51. if ($cachedXml) {
  52. Log::logHtml('caching for module # ' . $moduleName . ' enabled [got xml from cache]');
  53. $this->beforeCachedRun();
  54. $this->xmlPart = $cachedXml;
  55. }
  56. } else {
  57. Log::logHtml('caching for module # ' . $moduleName . ' disabled [module settings]');
  58. }
  59. }
  60. /**
  61. * перед тем как отдать данные из кеша выполняем эту ф-цию
  62. */
  63. protected function beforeCachedRun() {
  64. }
  65. protected function setPageTitle($title){
  66. XMLClass::$pageNode->setAttribute('title', $title);
  67. }
  68. protected function setPageDescriptionMeta($description){
  69. XMLClass::$pageNode->setAttribute('description', $description);
  70. }
  71. protected function setPageKeywordsMeta($keywords){
  72. XMLClass::$pageNode->setAttribute('keywords', $keywords);
  73. }
  74. protected function setCurrentView($view) {
  75. $this->props['current_view'] = $view;
  76. }
  77. protected function getCurrentView() {
  78. return $this->current_view;
  79. }
  80. protected function disableCaching() {
  81. $this->cache_enabled = false;
  82. }
  83. protected function dropCache() {
  84. $i = 0;
  85. $params = Request::getAllParameters();
  86. while ($i < count($params)) {
  87. $i++;
  88. $name = Request::$pageName . '_' . $this->moduleName . '_' . (implode('', array_slice($params,0,$i)));
  89. Cache::drop($name, Cache::DATA_TYPE_XML);
  90. }
  91. }
  92. protected function checkCacheSettings() {
  93. if ((isset($this->settings['cache']) && $this->settings['cache']) || (isset($this->props['params']['cache']) && $this->props['params']['cache'] )) {
  94. $this->xml_cache_name = Request::$pageName . '_' . $this->moduleName . '_' . (implode('', Request::getAllParameters()));
  95. $this->cache_enabled = true;
  96. if (isset($this->settings['xHTML']) && $this->settings['xHTML']) {
  97. if ((Request::$responseType == 'xsl') || (Request::$responseType == 'xml')) { // при просмотре xml и xslt отрубаем кеширование
  98. $this->cache_enabled = false;
  99. $this->xHTMLCachingEnabled = false;
  100. }else
  101. $this->xHTMLCachingEnabled = true;
  102. }
  103. }
  104. return $this->cache_enabled;
  105. }
  106. public function getProps() {
  107. return $this->props;
  108. }
  109. // генерируем xml дерево модуля
  110. public final function process() {
  111. if ($this->xmlPart !== false) {
  112. // xml уже взят
  113. $this->xmlPart->setAttribute('from_cache', true);
  114. return true;
  115. }
  116. $this->generateData();
  117. }
  118. protected function generateData() {
  119. throw new Exception($this->moduleName . '->generateData() must be implemented', Error::E_MUST_BE_IMPLEMENTED);
  120. }
  121. // пытаемся получить ноду из кеша
  122. protected function getFromCache() {
  123. if (!$this->cache_enabled)
  124. return false;
  125. if (isset($this->props['params']['cache_sec']))
  126. $cache_sec = (int) $this->props['params']['cache_sec'];
  127. if (isset($this->settings['cache_sec']))
  128. $cache_sec = (int) $this->settings['cache_sec'];
  129. if ($data = Cache::get($this->xml_cache_name, Cache::DATA_TYPE_XML, $cache_sec)) {
  130. Log::timingplus($this->moduleName . ' : XML from cache');
  131. $doc = new DOMDocument;
  132. $doc->loadXML($data);
  133. // говорим нашему дереву что этот кусок из кеша будет вставлен
  134. $part = $doc->getElementsByTagName("module")->item(0);
  135. $this->xmlPart = XMLClass::$xml->importNode($part, true);
  136. Log::timingplus($this->moduleName . ' : XML from cache');
  137. return $this->xmlPart;
  138. }
  139. return false;
  140. }
  141. // отправляем ноду в кеш
  142. protected function putInCache() {
  143. if ($this->cache_enabled) {
  144. if (isset($this->settings['cache_sec']))
  145. $cache_sec = (int) $this->settings['cache_sec'];
  146. Cache::set($this->xml_cache_name, XMLClass::$xml->saveXML($this->xmlPart), $cache_sec, Cache::DATA_TYPE_XML);
  147. Log::logHtml('caching for module # ' . $this->moduleName . ' enabled [put into cache]');
  148. }
  149. }
  150. public function getResultXML() {
  151. if ($this->xmlPart !== false)
  152. return $this->xmlPart;
  153. $this->xmlPart = XMLClass::createNodeFromObject(array('data' => $this->data, 'settings' => $this->settings), false, 'module');
  154. if ($this->xHTMLCachingEnabled) {
  155. Log::timingplus('BaseModule:xHTML generating #' . $this->moduleName);
  156. // процессим кусок XML с шаблоном, чтобы получить xHTML
  157. // шаблон, который отпроцессит только наш модуль - null.xsl
  158. $XSLClass = new XSLClass(LibPages::$pages[Request::$pageName]['xslt'], $xHTML = true);
  159. $arr = array($this->moduleName => $this->getXSLTFileName(true));
  160. // и шаблон модуля
  161. $XSLClass->setTemplates($arr);
  162. // создаем документ
  163. $xml = new DOMDocument('1.0', 'UTF-8');
  164. $xml->loadXML("<xml version=\"1.0\" encoding=\"utf-8\" >" . "<root></root></xml>");
  165. $rootNode = $xml->getElementsByTagName("root")->item(0);
  166. // нода page также нужна для корректной обработки шаблонаы
  167. $pageNode = $xml->importNode(XMLClass::$pageNode);
  168. $rootNode->appendChild($pageNode);
  169. // вставляем в него ноду с данными модуля
  170. $xHTMLnode = $xml->importNode($this->xmlPart, true);
  171. $rootNode->appendChild($xHTMLnode);
  172. $xHTMLnode->setAttribute('name', $this->moduleName);
  173. // теперь полученный xml процессим с шаблоном
  174. $xHTML = $XSLClass->getHTML($xml);
  175. // полученный xHTML нужно вбить в XML ноду "module"
  176. $xHTMLdoc = new DOMDocument('1.0', 'UTF-8');
  177. $xHTMLdoc->loadHTML($xHTML);
  178. $xpath = new DOMXPath($xHTMLdoc);
  179. $part = $xpath->query('body')->item(0);
  180. $part = $xHTMLdoc->importNode($part, true);
  181. // в part лежит HTML код
  182. // копируем его в новую ноду
  183. $NewElement = XMLClass::$xml->createElement('module');
  184. // Clone the attributes:
  185. foreach ($part->attributes as $attribute)
  186. $NewElement->setAttribute($attribute->name, $attribute->value);
  187. foreach ($part->childNodes as $child)
  188. $NewElement->appendChild(XMLClass::$xml->importNode($child, true));
  189. $this->xmlPart = $NewElement;
  190. Log::timingplus('BaseModule:xHTML generating #' . $this->moduleName);
  191. }
  192. $this->putInCache();
  193. return $this->xmlPart;
  194. }
  195. // сбрасываем кеш для данного модуля
  196. public function dropXMLCache() {
  197. return false;
  198. }
  199. // отдаем имя шаблона
  200. public function getXSLTFileName($ignoreXHTML = false) {
  201. if (!$ignoreXHTML && $this->xHTMLCachingEnabled) {
  202. // трансформация не нужна
  203. return null;
  204. }
  205. return $this->getXSLTFileNameView($ignoreXHTML);
  206. }
  207. public function getXSLTFileNameView($ignoreXHTML = false) {
  208. if (isset($this->props['xslt'])) {
  209. $xsltBaseName = $this->props['xslt'];
  210. // какая вьюшка применяется для модуля на этой конкретной странице?
  211. if ($this->props['current_view'])
  212. $xsltBaseName.= '_' . $this->props['current_view'];
  213. $this->props['current_view_template'] = $xsltBaseName;
  214. return $xsltBaseName;
  215. }
  216. return false;
  217. }
  218. }