PageRenderTime 27ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/phpmyfaq/src/phpMyFAQ/Glossary.php

http://github.com/thorsten/phpMyFAQ
PHP | 393 lines | 262 code | 35 blank | 96 comment | 9 complexity | 6fde1dbb6c39456360710f3f17b3ff48 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, LGPL-3.0
  1. <?php
  2. /**
  3. * The main glossary class.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public License,
  6. * v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. * obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. * @package phpMyFAQ
  10. * @author Thorsten Rinne <thorsten@phpmyfaq.de>
  11. * @copyright 2005-2021 phpMyFAQ Team
  12. * @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
  13. * @link https://www.phpmyfaq.de
  14. * @since 2005-09-15
  15. */
  16. namespace phpMyFAQ;
  17. /**
  18. * Class Glossary
  19. *
  20. * @package phpMyFAQ
  21. */
  22. class Glossary
  23. {
  24. /**
  25. * @var Configuration
  26. */
  27. private $config;
  28. /**
  29. * Item.
  30. *
  31. * @var array
  32. */
  33. private $item = [];
  34. /**
  35. * Definition of an item.
  36. *
  37. * @var string
  38. */
  39. private $definition = '';
  40. /**
  41. * Constructor.
  42. *
  43. * @param Configuration $config
  44. */
  45. public function __construct(Configuration $config)
  46. {
  47. $this->config = $config;
  48. }
  49. /**
  50. * Fill the passed string with the current Glossary items.
  51. *
  52. * @param string $content Content
  53. *
  54. * @return string
  55. */
  56. public function insertItemsIntoContent($content = '')
  57. {
  58. if ('' == $content) {
  59. return '';
  60. }
  61. $attributes = [
  62. 'href',
  63. 'src',
  64. 'title',
  65. 'alt',
  66. 'class',
  67. 'style',
  68. 'id',
  69. 'name',
  70. 'face',
  71. 'size',
  72. 'dir',
  73. 'rel',
  74. 'rev',
  75. 'onmouseenter',
  76. 'onmouseleave',
  77. 'onafterprint',
  78. 'onbeforeprint',
  79. 'onbeforeunload',
  80. 'onhashchange',
  81. 'onmessage',
  82. 'onoffline',
  83. 'ononline',
  84. 'onpopstate',
  85. 'onpagehide',
  86. 'onpageshow',
  87. 'onresize',
  88. 'onunload',
  89. 'ondevicemotion',
  90. 'ondeviceorientation',
  91. 'onabort',
  92. 'onblur',
  93. 'oncanplay',
  94. 'oncanplaythrough',
  95. 'onchange',
  96. 'onclick',
  97. 'oncontextmenu',
  98. 'ondblclick',
  99. 'ondrag',
  100. 'ondragend',
  101. 'ondragenter',
  102. 'ondragleave',
  103. 'ondragover',
  104. 'ondragstart',
  105. 'ondrop',
  106. 'ondurationchange',
  107. 'onemptied',
  108. 'onended',
  109. 'onerror',
  110. 'onfocus',
  111. 'oninput',
  112. 'oninvalid',
  113. 'onkeydown',
  114. 'onkeypress',
  115. 'onkeyup',
  116. 'onload',
  117. 'onloadeddata',
  118. 'onloadedmetadata',
  119. 'onloadstart',
  120. 'onmousedown',
  121. 'onmousemove',
  122. 'onmouseout',
  123. 'onmouseover',
  124. 'onmouseup',
  125. 'onpause',
  126. 'onplay',
  127. 'onplaying',
  128. 'onprogress',
  129. 'onratechange',
  130. 'onreset',
  131. 'onscroll',
  132. 'onseeked',
  133. 'onseeking',
  134. 'onselect',
  135. 'onshow',
  136. 'onstalled',
  137. 'onsubmit',
  138. 'onsuspend',
  139. 'ontimeupdate',
  140. 'onvolumechange',
  141. 'onwaiting',
  142. 'oncopy',
  143. 'oncut',
  144. 'onpaste',
  145. 'onbeforescriptexecute',
  146. 'onafterscriptexecute',
  147. ];
  148. foreach ($this->getAllGlossaryItems() as $item) {
  149. $this->definition = $item['definition'];
  150. $item['item'] = preg_quote($item['item'], '/');
  151. $content = Strings::preg_replace_callback(
  152. '/'
  153. // a. the glossary item could be an attribute name
  154. . '(' . $item['item'] . '="[^"]*")|'
  155. // b. the glossary item could be inside an attribute value
  156. . '((' . implode('|', $attributes) . ')="[^"]*' . $item['item'] . '[^"]*")|'
  157. // c. the glossary item could be everywhere as a distinct word
  158. . '(\W+)(' . $item['item'] . ')(\W+)|'
  159. // d. the glossary item could be at the beginning of the string as a distinct word
  160. . '^(' . $item['item'] . ')(\W+)|'
  161. // e. the glossary item could be at the end of the string as a distinct word
  162. . '(\W+)(' . $item['item'] . ')$'
  163. . '/mis',
  164. [$this, 'setTooltip'],
  165. $content,
  166. 1
  167. );
  168. }
  169. return $content;
  170. }
  171. /**
  172. * Gets all items and definitions from the database.
  173. *
  174. * @return array
  175. */
  176. public function getAllGlossaryItems()
  177. {
  178. $items = [];
  179. $query = sprintf(
  180. "
  181. SELECT
  182. id, item, definition
  183. FROM
  184. %sfaqglossary
  185. WHERE
  186. lang = '%s'
  187. ORDER BY item ASC",
  188. Database::getTablePrefix(),
  189. $this->config->getLanguage()->getLanguage()
  190. );
  191. $result = $this->config->getDb()->query($query);
  192. while ($row = $this->config->getDb()->fetchObject($result)) {
  193. $items[] = [
  194. 'id' => $row->id,
  195. 'item' => stripslashes($row->item),
  196. 'definition' => stripslashes($row->definition),
  197. ];
  198. }
  199. return $items;
  200. }
  201. /**
  202. * Callback function for filtering HTML from URLs and images.
  203. *
  204. * @param array $matches Matches
  205. *
  206. * @return string
  207. */
  208. public function setTooltip(array $matches)
  209. {
  210. $prefix = $postfix = '';
  211. if (count($matches) > 9) {
  212. // if the word is at the end of the string
  213. $prefix = $matches[9];
  214. $item = $matches[10];
  215. $postfix = '';
  216. } elseif (count($matches) > 7) {
  217. // if the word is at the beginning of the string
  218. $prefix = '';
  219. $item = $matches[7];
  220. $postfix = $matches[8];
  221. } elseif (count($matches) > 4) {
  222. // if the word is else where in the string
  223. $prefix = $matches[4];
  224. $item = $matches[5];
  225. $postfix = $matches[6];
  226. }
  227. if (!empty($item)) {
  228. return sprintf(
  229. '%s<abbr data-toggle="tooltip" data-placement="bottom" title="%s">%s</abbr>%s',
  230. $prefix,
  231. $this->definition,
  232. $item,
  233. $postfix
  234. );
  235. }
  236. // Fallback: the original matched string
  237. return $matches[0];
  238. }
  239. /**
  240. * Gets one item and definition from the database.
  241. *
  242. * @param int $id Glossary ID
  243. *
  244. * @return array
  245. */
  246. public function getGlossaryItem($id)
  247. {
  248. $item = [];
  249. $query = sprintf(
  250. "
  251. SELECT
  252. id, item, definition
  253. FROM
  254. %sfaqglossary
  255. WHERE
  256. id = %d AND lang = '%s'",
  257. Database::getTablePrefix(),
  258. (int)$id,
  259. $this->config->getLanguage()->getLanguage()
  260. );
  261. $result = $this->config->getDb()->query($query);
  262. while ($row = $this->config->getDb()->fetchObject($result)) {
  263. $item = [
  264. 'id' => $row->id,
  265. 'item' => stripslashes($row->item),
  266. 'definition' => stripslashes($row->definition),
  267. ];
  268. }
  269. return $item;
  270. }
  271. /**
  272. * Inserts an item and definition into the database.
  273. *
  274. * @param string $item Item
  275. * @param string $definition Definition
  276. *
  277. * @return bool
  278. */
  279. public function addGlossaryItem($item, $definition)
  280. {
  281. $this->item = $this->config->getDb()->escape($item);
  282. $this->definition = $this->config->getDb()->escape($definition);
  283. $query = sprintf(
  284. "
  285. INSERT INTO
  286. %sfaqglossary
  287. (id, lang, item, definition)
  288. VALUES
  289. (%d, '%s', '%s', '%s')",
  290. Database::getTablePrefix(),
  291. $this->config->getDb()->nextId(Database::getTablePrefix() . 'faqglossary', 'id'),
  292. $this->config->getLanguage()->getLanguage(),
  293. Strings::htmlspecialchars($this->item),
  294. Strings::htmlspecialchars($this->definition)
  295. );
  296. if ($this->config->getDb()->query($query)) {
  297. return true;
  298. }
  299. return false;
  300. }
  301. /**
  302. * Updates an item and definition into the database.
  303. *
  304. * @param int $id Glossary ID
  305. * @param string $item Item
  306. * @param string $definition Definition
  307. *
  308. * @return bool
  309. */
  310. public function updateGlossaryItem($id, $item, $definition)
  311. {
  312. $this->item = $this->config->getDb()->escape($item);
  313. $this->definition = $this->config->getDb()->escape($definition);
  314. $query = sprintf(
  315. "
  316. UPDATE
  317. %sfaqglossary
  318. SET
  319. item = '%s',
  320. definition = '%s'
  321. WHERE
  322. id = %d AND lang = '%s'",
  323. Database::getTablePrefix(),
  324. Strings::htmlspecialchars($this->item),
  325. Strings::htmlspecialchars($this->definition),
  326. (int)$id,
  327. $this->config->getLanguage()->getLanguage()
  328. );
  329. if ($this->config->getDb()->query($query)) {
  330. return true;
  331. }
  332. return false;
  333. }
  334. /**
  335. * Deletes an item and definition into the database.
  336. *
  337. * @param int $id Glossary ID
  338. *
  339. * @return bool
  340. */
  341. public function deleteGlossaryItem($id)
  342. {
  343. $query = sprintf(
  344. "
  345. DELETE FROM
  346. %sfaqglossary
  347. WHERE
  348. id = %d AND lang = '%s'",
  349. Database::getTablePrefix(),
  350. (int)$id,
  351. $this->config->getLanguage()->getLanguage()
  352. );
  353. if ($this->config->getDb()->query($query)) {
  354. return true;
  355. }
  356. return false;
  357. }
  358. }