/classes/help/PKPHelp.inc.php

https://github.com/davekisly/pkp-lib · PHP · 256 lines · 157 code · 31 blank · 68 comment · 33 complexity · ea642bd2c2e56640d9efc647e1b8dd73 MD5 · raw file

  1. <?php
  2. /**
  3. * @defgroup help
  4. */
  5. /**
  6. * @file classes/help/PKPHelp.inc.php
  7. *
  8. * Copyright (c) 2000-2011 John Willinsky
  9. * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
  10. *
  11. * @class PKPHelp
  12. * @ingroup help
  13. *
  14. * @brief Provides methods for translating help topic keys to their respected topic
  15. * help ids.
  16. */
  17. class PKPHelp {
  18. /** @var $mappingFiles array of HelpMappingFile objects */
  19. var $mappingFiles;
  20. /**
  21. * Get an instance of the Help object.
  22. */
  23. function &getHelp() {
  24. $instance =& Registry::get('help');
  25. if ($instance == null) {
  26. unset($instance);
  27. $application =& PKPApplication::getApplication();
  28. $instance =& $application->instantiateHelp();
  29. Registry::set('help', $instance);
  30. }
  31. return $instance;
  32. }
  33. /**
  34. * Constructor.
  35. */
  36. function PKPHelp() {
  37. $this->mappingFiles = array();
  38. }
  39. function &getMappingFiles() {
  40. return $this->mappingFiles;
  41. }
  42. function addMappingFile(&$mappingFile) {
  43. $this->mappingFiles[] =& $mappingFile;
  44. }
  45. /**
  46. * Get the locale to display help files in.
  47. * If help isn't available for the current locale,
  48. * defaults to en_US.
  49. */
  50. function getLocale() {
  51. $locale = AppLocale::getLocale();
  52. if (!file_exists("help/$locale/.")) {
  53. return 'en_US';
  54. }
  55. return $locale;
  56. }
  57. /**
  58. * Translate a help topic key to its numerical id.
  59. * @param $key string
  60. * @return string
  61. */
  62. function translate($key) {
  63. $key = trim($key);
  64. if (empty($key)) {
  65. return '';
  66. }
  67. $mappingFiles =& $this->getMappingFiles();
  68. for ($i=0; $i < count($mappingFiles); $i++) {
  69. // Not using foreach because it runs by value
  70. $mappingFile =& $mappingFiles[$i];
  71. $value = $mappingFile->map($key);
  72. if ($value !== null) return $value;
  73. unset($mappingFile);
  74. }
  75. if (!isset($value)) {
  76. return '##' . $key . '##';
  77. }
  78. }
  79. function &_getTocCache() {
  80. $cache =& Registry::get('pkpHelpTocCache', true, null);
  81. if ($cache === null) {
  82. $cacheManager =& CacheManager::getManager();
  83. $cache = $cacheManager->getFileCache(
  84. 'help', 'toc',
  85. array('Help', '_tocCacheMiss')
  86. );
  87. // Check to see if the cache info is outdated.
  88. $cacheTime = $cache->getCacheTime();
  89. if ($cacheTime !== null && $cacheTime < $this->dirmtime('help/'. $this->getLocale() . '/.', true)) {
  90. // The cached data is out of date.
  91. $cache->flush();
  92. }
  93. }
  94. return $cache;
  95. }
  96. function _mappingCacheMiss(&$cache, $id) {
  97. // Keep a secondary cache of the mappings so that a few
  98. // cache misses won't destroy the server
  99. $mappings =& Registry::get('pkpHelpMappings', true, null);
  100. $result = null;
  101. if (HookRegistry::call('Help::_mappingCacheMiss', array(&$cache, &$id, &$mappings, &$result))) return $result;
  102. if ($mappings === null) {
  103. $mappings =& $this->loadHelpMappings();
  104. $cache->setEntireCache($mappings);
  105. }
  106. return isset($mappings[$id])?$mappings[$id]:null;
  107. }
  108. function _tocCacheMiss(&$cache, $id) {
  109. // Keep a secondary cache of the TOC so that a few
  110. // cache misses won't destroy the server
  111. $toc =& Registry::get('pkpHelpTocData', true, null);
  112. if ($toc === null) {
  113. $helpToc = array();
  114. $topicId = 'index/topic/000000';
  115. $help =& Help::getHelp();
  116. $helpToc = $help->buildTopicSection($topicId);
  117. $toc =& $help->buildToc($helpToc);
  118. $cache->setEntireCache($toc);
  119. }
  120. return null;
  121. }
  122. /**
  123. * Load table of contents from xml help topics and their tocs
  124. * (return cache, if available)
  125. * @return array associative array of topics and subtopics
  126. */
  127. function &getTableOfContents() {
  128. $cache =& $this->_getTocCache();
  129. return $cache->getContents();
  130. }
  131. /**
  132. * Modifies retrieved array of topics and arranges them into toc
  133. * @param $helpToc array
  134. * @return array
  135. */
  136. function &buildToc($helpToc) {
  137. $toc = array();
  138. foreach($helpToc as $topicId => $section) {
  139. $toc[$topicId] = array('title' => $section['title'], 'prefix' => '');
  140. $this->buildTocHelper($toc, $section['section'], '');
  141. }
  142. return $toc;
  143. }
  144. /**
  145. * Helper method for buildToc
  146. * @param $helpToc array
  147. * @param $section array
  148. * @param $num numbering of topic
  149. */
  150. function buildTocHelper(&$toc, $section, $prefix) {
  151. if (isset($section)) {
  152. $prefix = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$prefix";
  153. foreach($section as $topicId => $sect) {
  154. $toc[$topicId] = array('title' => $sect['title'], 'prefix' => $prefix);
  155. $this->buildTocHelper($toc, $sect['section'], $prefix);
  156. }
  157. }
  158. }
  159. /**
  160. * Helper method for getTableOfContents
  161. * @param $topicId int
  162. * @param $prevTocId int
  163. * @return array
  164. */
  165. function buildTopicSection($topicId, $prevTocId = null) {
  166. $topicDao =& DAORegistry::getDAO('HelpTopicDAO');
  167. $tocDao =& DAORegistry::getDAO('HelpTocDAO');
  168. $topic = $topicDao->getTopic($topicId);
  169. if ($topicId == 'index/topic/000000') {
  170. $tocId = $topic->getTocId();
  171. } else {
  172. $tocId = $topic->getSubTocId();
  173. }
  174. $section = array();
  175. if ($tocId && $tocId != $prevTocId) {
  176. $toc = $tocDao->getToc($tocId);
  177. $topics = $toc->getTopics();
  178. foreach($topics as $currTopic) {
  179. $currId = $currTopic->getId();
  180. $currTitle = $currTopic->getTitle();
  181. if ($currId != $topicId) {
  182. $section[$currId] = array('title' => $currTitle, 'section' => $this->buildTopicSection($currId, $tocId));
  183. }
  184. }
  185. }
  186. if (empty($section)) {
  187. $section = null;
  188. }
  189. return $section;
  190. }
  191. /**
  192. * Returns the most recent modified file in the specified directory
  193. * Taken from the php.net site under filemtime
  194. * @param $dirName string
  195. * @param $doRecursive bool
  196. * @return int
  197. */
  198. function dirmtime($dirName,$doRecursive) {
  199. $d = dir($dirName);
  200. $lastModified = 0;
  201. while($entry = $d->read()) {
  202. if ($entry != "." && $entry != "..") {
  203. if (!is_dir($dirName."/".$entry)) {
  204. $currentModified = filemtime($dirName."/".$entry);
  205. } else if ($doRecursive && is_dir($dirName."/".$entry)) {
  206. $currentModified = $this->dirmtime($dirName."/".$entry,true);
  207. }
  208. if ($currentModified > $lastModified) {
  209. $lastModified = $currentModified;
  210. }
  211. }
  212. }
  213. $d->close();
  214. return $lastModified;
  215. }
  216. function getSearchPaths() {
  217. $mappingFiles =& $this->getMappingFiles();
  218. $searchPaths = array();
  219. for ($i = 0; $i < count($mappingFiles); $i++) {
  220. $searchPaths[$mappingFiles[$i]->getSearchPath()] =& $mappingFiles[$i];
  221. }
  222. return $searchPaths;
  223. }
  224. }
  225. ?>