PageRenderTime 32ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/e107_handlers/plugin_class.php

https://github.com/CasperGemini/e107
PHP | 3036 lines | 2533 code | 248 blank | 255 comment | 274 complexity | 8e40a66ec74b29e40ff321d4d8b8aa59 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. * e107 website system
  4. *
  5. * Copyright (C) 2008-2013 e107 Inc (e107.org)
  6. * Released under the terms and conditions of the
  7. * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
  8. *
  9. */
  10. if (!defined('e107_INIT')) { exit; }
  11. /**
  12. *
  13. * @package e107
  14. * @category e107_handlers
  15. * @author e107inc
  16. *
  17. * Plugin administration handler
  18. */
  19. // TODO LAN
  20. e107::coreLan('plugin', true);
  21. class e107plugin
  22. {
  23. // Reserved Addon names.
  24. var $plugin_addons = array(
  25. 'e_bb',
  26. 'e_cron',
  27. 'e_notify',
  28. 'e_linkgen',
  29. 'e_list',
  30. 'e_meta',
  31. 'e_emailprint',
  32. 'e_frontpage',
  33. 'e_latest',
  34. 'e_status',
  35. 'e_search',
  36. 'e_shortcode',
  37. 'e_module',
  38. 'e_event',
  39. 'e_comment',
  40. 'e_sql',
  41. 'e_userprofile',
  42. 'e_header',
  43. 'e_userinfo',
  44. 'e_tagwords',
  45. 'e_url',
  46. 'e_mailout',
  47. 'e_sitelink',
  48. 'e_tohtml',
  49. 'e_featurebox',
  50. 'e_related',
  51. 'e_rss',
  52. );
  53. var $disAllowed = array(
  54. 'theme',
  55. 'core'
  56. );
  57. protected $core_plugins = array(
  58. "_blank","admin_menu","alt_auth","banner","blogcalendar_menu",
  59. "calendar_menu","chatbox_menu", "clock_menu","comment_menu",
  60. "contact", "download","faqs", "featurebox", "forum","gallery",
  61. "gsitemap","import", "linkwords", "list_new", "log", "login_menu",
  62. "metaweblog", "newforumposts_main", "news", "newsfeed",
  63. "newsletter","online", "page", "pdf", "pm", "pm","poll",
  64. "rss_menu","search_menu","siteinfo", "social", "tagwords", "tinymce",
  65. "trackback","tree_menu","user"
  66. );
  67. // List of all plugin variables which need to be checked - install required if one or more set and non-empty
  68. // Deprecated in 0.8 (used in plugin.php only). Probably delete in 0.9
  69. var $all_eplug_install_variables = array(
  70. 'eplug_link_url',
  71. 'eplug_link',
  72. 'eplug_prefs',
  73. 'eplug_array_pref',
  74. 'eplug_table_names',
  75. // 'eplug_sc', // Not used in 0.8 (or later 0.7)
  76. 'eplug_userclass',
  77. 'eplug_module',
  78. // 'eplug_bb', // Not used in 0.8 (or later 0.7)
  79. 'eplug_latest',
  80. 'eplug_status',
  81. 'eplug_comment_ids',
  82. 'eplug_conffile',
  83. 'eplug_menu_name'
  84. );
  85. // List of all plugin variables involved in an update (not used ATM, but worth 'documenting')
  86. // Deprecated in 0.8 (used in plugin.php only). Probably delete in 0.9
  87. var $all_eplug_update_variables = array(
  88. 'upgrade_alter_tables',
  89. // 'upgrade_add_eplug_sc', // Not used in 0.8 (or later 0.7)
  90. // 'upgrade_remove_eplug_sc', // Not used in 0.8 (or later 0.7)
  91. // 'upgrade_add_eplug_bb', // Not used in 0.8 (or later 0.7)
  92. // 'upgrade_remove_eplug_bb', // Not used in 0.8 (or later 0.7)
  93. 'upgrade_add_prefs',
  94. 'upgrade_remove_prefs',
  95. 'upgrade_add_array_pref',
  96. 'upgrade_remove_array_pref'
  97. );
  98. // List of all 'editable' DB fields ('plugin_id' is an arbitrary reference which is never edited)
  99. var $all_editable_db_fields = array(
  100. 'plugin_name', // Name of the plugin - language dependent
  101. 'plugin_version', // Version - arbitrary text field
  102. 'plugin_path', // Name of the directory off e_PLUGIN - unique
  103. 'plugin_installflag', // '0' = not installed, '1' = installed
  104. 'plugin_addons', // List of any extras associated with plugin - bbcodes, e_XXX files...
  105. 'plugin_category' // Plugin Category: settings, users, content, management, tools, misc, about
  106. );
  107. var $accepted_categories = array('settings', 'users', 'content', 'tools', 'manage', 'misc', 'menu', 'about');
  108. var $plug_vars;
  109. var $current_plug;
  110. var $parsed_plugin = array();
  111. var $plugFolder;
  112. var $plugConfigFile;
  113. var $unInstallOpts;
  114. var $module = array();
  115. private $options = array();
  116. function __construct()
  117. {
  118. //$parsed_plugin = array();
  119. }
  120. /**
  121. * Returns an array containing details of all plugins in the plugin table - should normally use e107plugin::update_plugins_table() first to
  122. * make sure the table is up to date. (Primarily called from plugin manager to get lists of installed and uninstalled plugins.
  123. * @return array plugin details
  124. */
  125. function getall($flag)
  126. {
  127. $sql = e107::getDb();
  128. if($flag === 'all')
  129. {
  130. $qry = "SELECT * FROM #plugin ORDER BY plugin_path ASC";
  131. }
  132. else
  133. {
  134. $qry = "SELECT * FROM #plugin WHERE plugin_installflag = ".(int) $flag." ORDER BY plugin_path ASC";
  135. }
  136. if ($sql->gen($qry))
  137. {
  138. $ret = $sql->db_getList();
  139. return $ret;
  140. }
  141. return false;
  142. }
  143. /**
  144. * Return a list of core plugins.
  145. */
  146. public function getCorePlugins()
  147. {
  148. return $this->core_plugins;
  149. }
  150. /**
  151. * Return a list of non-core plugins
  152. */
  153. public function getOtherPlugins()
  154. {
  155. $allplugs = e107::getFile()->get_dirs(e_PLUGIN);
  156. return array_diff($allplugs,$this->core_plugins);
  157. }
  158. /**
  159. * Returns an array containing details of all plugins in the plugin table - should normally use e107plugin::update_plugins_table() first to
  160. * make sure the table is up to date. (Primarily called from plugin manager to get lists of installed and uninstalled plugins.
  161. * @return array plugin details
  162. */
  163. function getId($path)
  164. {
  165. $sql = e107::getDb();
  166. if ($sql->select("plugin", "plugin_id", "plugin_path = '".(string) $path."' LIMIT 1"))
  167. {
  168. $row = $sql->fetch(MYSQL_ASSOC);
  169. return intval($row['plugin_id']);
  170. }
  171. return false;
  172. }
  173. /**
  174. * Checks all installed plugins and returns an array of those needing an update.
  175. * @param string $mode 'boolean' for a quick true/false or null for full array returned.
  176. * @return mixed
  177. */
  178. function updateRequired($mode=null)
  179. {
  180. $xml = e107::getXml();
  181. $mes = e107::getMessage();
  182. $needed = array();
  183. $log = e107::getAdminLog();
  184. if(!$plugVersions = e107::getConfig('core')->get('plug_installed'))
  185. {
  186. return FALSE;
  187. }
  188. foreach($plugVersions as $path=>$version)
  189. {
  190. $fullPath = e_PLUGIN.$path."/plugin.xml";
  191. if(is_file(e_PLUGIN.$path."/plugin.xml"))
  192. {
  193. $data = $xml->loadXMLfile($fullPath, true);
  194. $curVal = floatval($version);
  195. $fileVal = floatval($data['@attributes']['version']);
  196. if($ret = $this->execute_function($path, 'upgrade', 'required', array($this, $curVal, $fileVal))) // Check {plugin}_setup.php and run a 'required' method, if true, then update is required.
  197. {
  198. if($mode == 'boolean')
  199. {
  200. $mes->addDebug("Plugin Update(s) Required");
  201. return TRUE;
  202. }
  203. $needed[$path] = $data;
  204. }
  205. if($curVal < $fileVal)
  206. {
  207. if($mode == 'boolean')
  208. {
  209. $mes->addDebug("Plugin Update(s) Required");
  210. return TRUE;
  211. }
  212. // $mes->addDebug("Plugin: <strong>{$path}</strong> requires an update.");
  213. // $log->flushMessages();
  214. $needed[$path] = $data;
  215. }
  216. }
  217. }
  218. // Display debug and log to file.
  219. foreach($needed as $path=>$tmp)
  220. {
  221. $log->addDebug("Plugin: <strong>{$path}</strong> requires an update.");
  222. }
  223. return count($needed) ? $needed : FALSE;
  224. }
  225. /**
  226. * Check for new plugins, create entry in plugin table and remove deleted plugins
  227. *
  228. * @param string $mode = install|upgrade|refresh|uninstall - defines the intent of the call
  229. *
  230. * 'upgrade' and 'refresh' are very similar in intent, and often take the same actions:
  231. * 'upgrade' signals a possible change to the installed list of plugins
  232. * 'refresh' validates the stored data for existing plugins, recreating any that has gone missing
  233. */
  234. function update_plugins_table($mode = 'upgrade')
  235. {
  236. $sql = e107::getDb();
  237. $sql2 = e107::getDb('sql2');
  238. $tp = e107::getParser();
  239. $fl = e107::getFile();
  240. $mes = e107::getMessage();
  241. $mes->addDebug("Updating plugins Table");
  242. $log = e107::getAdminLog();
  243. global $mySQLprefix, $menu_pref;
  244. $pref = e107::getPref();
  245. $sp = FALSE;
  246. $pluginDBList = array();
  247. if ($sql->select('plugin', "*")) // Read all the plugin DB info into an array to save lots of accesses
  248. {
  249. while ($row = $sql->fetch(MYSQL_ASSOC))
  250. {
  251. $pluginDBList[$row['plugin_path']] = $row;
  252. $pluginDBList[$row['plugin_path']]['status'] = 'read';
  253. // echo "Found plugin: ".$row['plugin_path']." in DB<br />";
  254. }
  255. }
  256. $sql->db_Mark_Time('Start Scanning Plugin Files');
  257. $plugList = $fl->get_files(e_PLUGIN, "^plugin\.(php|xml)$", "standard", 1);
  258. foreach ($plugList as $num => $val) // Remove Duplicates caused by having both plugin.php AND plugin.xml.
  259. {
  260. $key = basename($val['path']);
  261. $pluginList[$key] = $val;
  262. }
  263. $sql->db_Mark_Time('After Scanning Plugin Files');
  264. $p_installed = e107::getPref('plug_installed', array()); // load preference;
  265. $mes = e107::getMessage();
  266. foreach ($pluginList as $p)
  267. {
  268. $p['path'] = substr(str_replace(e_PLUGIN, "", $p['path']), 0, -1);
  269. $plugin_path = $p['path'];
  270. if (strpos($plugin_path, 'e107_') !== FALSE)
  271. {
  272. $mes->addWarning("Folder error: <i>{$p['path']}</i>. 'e107_' is not permitted within plugin folder names.");
  273. continue;
  274. }
  275. if(in_array($plugin_path, $this->disAllowed))
  276. {
  277. $mes->addWarning("Folder error: <i>{$p['path']}</i> is not permitted as an acceptable folder name.");
  278. continue;
  279. }
  280. $plug['plug_action'] = 'scan'; // Make sure plugin.php knows what we're up to
  281. if (!$this->parse_plugin($p['path']))
  282. {
  283. //parsing of plugin.php/plugin.xml failed.
  284. $mes->addError("Parsing failed - file format error: {$p['path']}");
  285. continue; // Carry on and do any others that are OK
  286. }
  287. $plug_info = $this->plug_vars;
  288. $eplug_addons = $this->getAddons($plugin_path);
  289. //Ensure the plugin path lives in the same folder as is configured in the plugin.php/plugin.xml - no longer relevant.
  290. if ($plugin_path == $plug_info['folder'])
  291. {
  292. if (array_key_exists($plugin_path, $pluginDBList))
  293. { // Update the addons needed by the plugin
  294. $pluginDBList[$plugin_path]['status'] = 'exists';
  295. // Check for name (lan) changes
  296. if (vartrue($plug_info['@attributes']['lan']) && $pluginDBList[$plugin_path]['plugin_name'] != $plug_info['@attributes']['lan'])
  297. {
  298. // print_a($plug_info);
  299. $pluginDBList[$plugin_path]['status'] = 'update';
  300. $pluginDBList[$plugin_path]['plugin_name'] = $plug_info['@attributes']['lan'];
  301. $this->plugFolder = $plugin_path;
  302. $this->XmlLanguageFiles('upgrade');
  303. }
  304. if ($mode == 'refresh')
  305. {
  306. if ($this->XmlLanguageFileCheck('_log', 'lan_log_list', 'refresh', $pluginDBList[$plugin_path]['plugin_installflag'], FALSE, $plugin_path)) $sp = TRUE;
  307. if ($this->XmlLanguageFileCheck('_global', 'lan_global_list', 'refresh', $pluginDBList[$plugin_path]['plugin_installflag'], TRUE, $plugin_path)) $sp = TRUE;
  308. }
  309. // Check for missing plugin_category in plugin table.
  310. if ($pluginDBList[$plugin_path]['plugin_category'] == '' || $pluginDBList[$plugin_path]['plugin_category'] != $plug_info['category'])
  311. {
  312. // print_a($plug_info);
  313. $pluginDBList[$plugin_path]['status'] = 'update';
  314. $pluginDBList[$plugin_path]['plugin_category'] = (varsettrue($plug_info['category'])) ? $plug_info['category'] : "misc";
  315. }
  316. // If plugin not installed, and version number of files changed, update version as well
  317. if (($pluginDBList[$plugin_path]['plugin_installflag'] == 0) && ($pluginDBList[$plugin_path]['plugin_version'] != $plug_info['@attributes']['version']))
  318. { // Update stored version
  319. $pluginDBList[$plugin_path]['plugin_version'] = $plug_info['@attributes']['version'];
  320. $pluginDBList[$plugin_path]['status'] = 'update';
  321. }
  322. if ($pluginDBList[$plugin_path]['plugin_addons'] != $eplug_addons)
  323. { // Update stored addons list
  324. $pluginDBList[$plugin_path]['plugin_addons'] = $eplug_addons;
  325. $pluginDBList[$plugin_path]['status'] = 'update';
  326. }
  327. if ($pluginDBList[$plugin_path]['plugin_installflag'] == 0) // Plugin not installed - make sure $pref not set
  328. {
  329. if (isset($p_installed[$plugin_path]))
  330. {
  331. unset($p_installed[$plugin_path]);
  332. $sp = TRUE;
  333. }
  334. }
  335. else
  336. { // Plugin installed - make sure $pref is set
  337. if (!isset($p_installed[$plugin_path]) || ($p_installed[$plugin_path] != $pluginDBList[$plugin_path]['plugin_version']))
  338. { // Update prefs array of installed plugins
  339. $p_installed[$plugin_path] = $pluginDBList[$plugin_path]['plugin_version'];
  340. // echo "Add: ".$plugin_path."->".$ep_row['plugin_version']."<br />";
  341. $sp = TRUE;
  342. }
  343. }
  344. }
  345. else // New plugin - not in table yet, so add it. If no install needed, mark it as 'installed'
  346. {
  347. if ($plug_info['@attributes']['name'])
  348. {
  349. $pName = vartrue($plug_info['@attributes']['lan']) ? $plug_info['@attributes']['lan'] : $plug_info['@attributes']['name'] ;
  350. $_installed = ($plug_info['@attributes']['installRequired'] == 'true' || $plug_info['@attributes']['installRequired'] == 1 ? 0 : 1);
  351. $pInsert = array(
  352. 'plugin_id' => 0,
  353. 'plugin_name' => $tp->toDB($pName, true),
  354. 'plugin_version' => $tp->toDB($plug_info['@attributes']['version'], true),
  355. 'plugin_path' => $tp->toDB($plugin_path, true),
  356. 'plugin_installflag' => $_installed,
  357. 'plugin_addons' => $eplug_addons,
  358. 'plugin_category' => $this->manage_category($plug_info['category'])
  359. );
  360. // if (e107::getDb()->db_Insert("plugin", "0, '".$tp->toDB($pName, true)."', '".$tp->toDB($plug_info['@attributes']['version'], true)."', '".$tp->toDB($plugin_path, true)."',{$_installed}, '{$eplug_addons}', '".$this->manage_category($plug_info['category'])."' "))
  361. if (e107::getDb()->insert("plugin", $pInsert))
  362. {
  363. $log->addDebug("Added <b>".$tp->toHTML($pName,false,"defs")."</b> to the plugin table.");
  364. }
  365. else
  366. {
  367. $log->addDebug("Failed to add ".$tp->toHTML($pName,false,"defs")." to the plugin table.");
  368. }
  369. $log->flushMessages("Updated Plugins table");
  370. }
  371. }
  372. }
  373. else
  374. { // May be useful that we ignore what will usually be copies/backups of plugins - but don't normally say anything
  375. // echo "Plugin copied to wrong directory. Is in: {$plugin_path} Should be: {$plug_info['folder']}<br /><br />";
  376. }
  377. // print_a($plug_info);
  378. }
  379. // Now scan the table, updating the DB where needed
  380. foreach ($pluginDBList as $plug_path => $plug_info)
  381. {
  382. if ($plug_info['status'] == 'read')
  383. { // In table, not on server - delete it
  384. $sql->delete('plugin', "`plugin_id`={$plug_info['plugin_id']}");
  385. // echo "Deleted: ".$plug_path."<br />";
  386. }
  387. if ($plug_info['status'] == 'update')
  388. {
  389. $temp = array();
  390. foreach ($this->all_editable_db_fields as $p_f)
  391. {
  392. $temp[] = "`{$p_f}` = '{$plug_info[$p_f]}'";
  393. }
  394. $sql->update('plugin', implode(", ", $temp)." WHERE `plugin_id`={$plug_info['plugin_id']}");
  395. // echo "Updated: ".$plug_path."<br />";
  396. }
  397. }
  398. if ($sp/* && vartrue($p_installed)*/)
  399. {
  400. e107::getConfig('core')->setPref('plug_installed', $p_installed);
  401. $this->rebuildUrlConfig();
  402. e107::getConfig('core')->save();
  403. }
  404. }
  405. function manage_category($cat)
  406. {
  407. if (vartrue($cat) && in_array($cat, $this->accepted_categories))
  408. {
  409. return $cat;
  410. }
  411. else
  412. {
  413. return 'misc';
  414. }
  415. }
  416. function manage_icons($plugin = '', $function = '')
  417. {
  418. if ($plugin == '')
  419. {
  420. return;
  421. }
  422. $mes = e107::getMessage();
  423. $sql = e107::getDb();
  424. $tp = e107::getParser();
  425. $med = e107::getMedia();
  426. if ($function == 'install' || $function == 'upgrade')
  427. {
  428. $med->importIcons(e_PLUGIN.$plugin);
  429. return;
  430. }
  431. if ($function == 'uninstall')
  432. {
  433. if (vartrue($this->unInstallOpts['delete_ipool'], FALSE))
  434. {
  435. $status = ($med->removePath(e_PLUGIN.$plugin, 'icon')) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  436. $mes->add('Removing Icons from Media-Manager', $status);
  437. }
  438. return;
  439. }
  440. }
  441. /**
  442. * Returns details of a plugin from the plugin table from it's ID
  443. *
  444. * @param int $id
  445. * @return array plugin info
  446. */
  447. function getinfo($id, $force = false)
  448. {
  449. $sql = e107::getDb();
  450. static $getinfo_results;
  451. if (!is_array($getinfo_results))
  452. {
  453. $getinfo_results = array();
  454. }
  455. $path = (!is_numeric($id)) ? $id : false;
  456. $id = (int) $id;
  457. $qry = "plugin_id = ".$id;
  458. $qry .= ($path != false) ? " OR plugin_path = '".$path."' " : "";
  459. if (!isset($getinfo_results[$id]) || $force == true)
  460. {
  461. if ($sql->select('plugin', '*', $qry))
  462. {
  463. $getinfo_results[$id] = $sql->fetch();
  464. }
  465. else
  466. {
  467. return false;
  468. }
  469. }
  470. return $getinfo_results[$id];
  471. }
  472. public function setUe()
  473. {
  474. if (!isset($this->module['ue']))
  475. {
  476. include_once(e_HANDLER.'user_extended_class.php');
  477. $this->module['ue'] = new e107_user_extended;
  478. }
  479. }
  480. /**
  481. * User field name, based on its type
  482. * @param string $folder plugin folder
  483. * @param int $type normalized field type
  484. * @param string $name field name
  485. * @return string field name
  486. */
  487. public function ue_field_name($folder, $type, $name)
  488. {
  489. if($type == EUF_PREFIELD || $type == EUF_CATEGORY)
  490. {
  491. return $name; // no plugin_plugname_ prefix
  492. }
  493. return 'plugin_'.$folder.'_'.$name;
  494. }
  495. /**
  496. * Normalize type
  497. * @param array $attrib parsed from XML user field definitions
  498. * @return integer type ID
  499. */
  500. public function ue_field_type($attrib)
  501. {
  502. $field_type = $attrib['type'];
  503. $type = defined($field_type) ? constant($field_type) : $field_type;
  504. if(!is_numeric($type))
  505. {
  506. // normalize further
  507. $this->setUe();
  508. $type = $this->module['ue']->typeArray[$type];
  509. }
  510. return $type;
  511. }
  512. /**
  513. * Type number to type name
  514. * @param integer $typeId
  515. * @return string type name
  516. */
  517. public function ue_field_type_name($typeId)
  518. {
  519. if(is_numeric($typeId))
  520. {
  521. $this->setUe();
  522. return array_search($typeId, $this->module['ue']->typeArray);
  523. }
  524. return $typeId;
  525. }
  526. /**
  527. * Field attributes ($field_attrib array) as they have to be defined in plugin.xml:
  528. * name - REQUIRED string
  529. * text - (string|constant name) field label
  530. * type - REQUIRED (constant name) see EUF_* constants in e107_user_extended class
  531. * regex - regex validation string
  532. * required - 0-not requried, don't show on signup; 1 - required, show on signup; 2-not required, show on signup
  533. * allow_hide (0|1) - allow user to hide this field on profile page
  534. * read, write, applicable - classes, see e_UC_* defines
  535. * values - comma separated values (if required)
  536. * default - default value
  537. * order - (number)
  538. * parent - (string) category name for this field
  539. * system - (0|1) - field wont be shown if it's system, NOTE - default value if system is not set is 1!
  540. *
  541. * @param string $action - add|remove
  542. * @param string $field_name normalized field name (see self::ue_field_name())
  543. * @param array $field_attrib
  544. * @param string $field_source used for system user fields
  545. *
  546. * @return boolean success
  547. */
  548. function manage_extended_field($action, $field_name, $field_attrib, $field_source = '')
  549. {
  550. $mes = e107::getMessage();
  551. $this->setUe();
  552. $type = $this->ue_field_type($field_attrib);
  553. $type_name = $this->ue_field_type_name($type);
  554. $mes->addDebug("Extended Field: ".$action.": ".$field_name." : ".$type_name);
  555. // predefined
  556. if($type == EUF_PREFIELD)
  557. {
  558. $preList = $this->module['ue']->parse_extended_xml(''); // passed value currently not used at all, could be file path in the near future
  559. if($preList && isset($preList[$field_name]))
  560. {
  561. $preField = $preList[$field_name];
  562. if($preField)
  563. {
  564. $field_attrib = array_merge($preField, $field_attrib); // merge
  565. // predefined type - numeric value, constant or as defined in user_extended_class::typeArray
  566. $field_attrib['type'] = $type = $this->ue_field_type($preField); // override type
  567. }
  568. else
  569. {
  570. return false;
  571. }
  572. }
  573. }
  574. // not allowed for categories
  575. elseif($type == EUF_CATEGORY)
  576. {
  577. $field_attrib['parent'] = 0;
  578. }
  579. if ($action == 'add')
  580. {
  581. // system field
  582. if($field_attrib['system'])
  583. {
  584. return $this->module['ue']->user_extended_add_system($field_name, $type, varset($field_attrib['default'], ''), $field_source);
  585. }
  586. // new - add non-system extended field
  587. // classes
  588. $field_attrib['read'] = varset($field_attrib['read'], 'e_UC_MEMBER');
  589. $field_attrib['write'] = varset($field_attrib['read'], 'e_UC_MEMBER');
  590. $field_attrib['applicable'] = varset($field_attrib['applicable'], 'e_UC_MEMBER');
  591. // manage parent
  592. if(vartrue($field_attrib['parent']))
  593. {
  594. foreach ($this->module['ue']->catDefinitions as $key => $value)
  595. {
  596. if($value['user_extended_struct_name'] == $field_attrib['parent'])
  597. {
  598. $field_attrib['parent'] = $key;
  599. break;
  600. }
  601. }
  602. if(!is_numeric($field_attrib['parent'])) $field_attrib['parent'] = 0;
  603. }
  604. else $field_attrib['parent'] = 0;
  605. // manage required (0, 1, 2)
  606. if(!isset($field_attrib['required']))
  607. {
  608. $field_attrib['required'] = 0;
  609. }
  610. // manage params
  611. $field_attrib['parms'] = '';
  612. // validation and parms
  613. $include = varset($field_attrib['include_text']);
  614. $regex = varset($field_attrib['regex']);
  615. $hide = vartrue($field_attrib['allow_hide']) ? 1 : 0;
  616. $failmsg = '';
  617. if($regex || $hide)
  618. {
  619. // failmsg only when required
  620. if($field_attrib['required'] == 1 || $regex)
  621. $failmsg = vartrue($field_attrib['error']) ? $field_attrib['error'] : 'LAN_UE_FAIL_'.strtoupper($field_name);
  622. $field_attrib['parms'] = $include."^,^".$regex."^,^".$failmsg.'^,^'.$hide;
  623. }
  624. //var_dump($field_attrib, $field_name, $type);
  625. $status = $this->module['ue']->user_extended_add(
  626. $field_name,
  627. varset($field_attrib['text'], "LAN_UE_".strtoupper($field_name)),
  628. $type,
  629. $field_attrib['parms'],
  630. varset($field_attrib['values'], ''),
  631. varset($field_attrib['default'], ''),
  632. $field_attrib['required'],
  633. defset($field_attrib['read'], e_UC_MEMBER),
  634. defset($field_attrib['write'], e_UC_MEMBER),
  635. defset($field_attrib['applicable'], e_UC_MEMBER),
  636. varset($field_attrib['order'], ''),
  637. $field_attrib['parent']
  638. );
  639. // db fields handling
  640. if($status && $type == EUF_DB_FIELD)
  641. {
  642. // handle DB, use original non-modified name value
  643. $status = !$this->manage_extended_field_sql('add', $field_attrib['name']); // reverse logic - sql method do a error check
  644. }
  645. // refresh categories - sadly the best way so far... need improvement (inside ue class)
  646. if($status && $type == EUF_CATEGORY)
  647. {
  648. $cats = $this->module['ue']->user_extended_get_categories(false);
  649. foreach ($cats as $cat)
  650. {
  651. $this->module['ue']->catDefinitions[$cat['user_extended_struct_id']] = $cat;
  652. }
  653. }
  654. return $status;
  655. }
  656. if ($action == 'remove')
  657. {
  658. //var_dump($field_attrib, $field_name, $type);
  659. $status = $this->module['ue']->user_extended_remove($field_name, $field_name);
  660. if($status && $type == EUF_DB_FIELD)
  661. {
  662. $status = $this->manage_extended_field_sql('remove', $field_attrib['name']);
  663. }
  664. return $status;
  665. }
  666. return false;
  667. }
  668. function manage_extended_field_sql($action, $field_name)
  669. {
  670. $f = e_CORE.'sql/extended_'.preg_replace('/[^\w]/', '', $field_name).'.php'; // quick security, always good idea
  671. if(!is_readable($f)) return false;
  672. // TODO - taken from user_extended Administration, need to be refined :/
  673. // FIXME - use sql parse handler
  674. $error = FALSE;
  675. $count = 0;
  676. if($action == 'add')
  677. {
  678. $sql_data = file_get_contents($f);
  679. $search[0] = "CREATE TABLE "; $replace[0] = "CREATE TABLE ".MPREFIX;
  680. $search[1] = "INSERT INTO "; $replace[1] = "INSERT INTO ".MPREFIX;
  681. preg_match_all("/create(.*?)myisam;/si", $sql_data, $creation);
  682. foreach($creation[0] as $tab)
  683. {
  684. $query = str_replace($search,$replace,$tab);
  685. if(!mysql_query($query))
  686. {
  687. $error = TRUE;
  688. }
  689. $count++;
  690. }
  691. preg_match_all("/insert(.*?);/si", $sql_data, $inserts);
  692. foreach($inserts[0] as $ins)
  693. {
  694. $qry = str_replace($search,$replace,$ins);
  695. if(!mysql_query($qry))
  696. {
  697. $error = TRUE;
  698. }
  699. $count++;
  700. }
  701. if(!$count) $error = TRUE;
  702. return $error;
  703. }
  704. //remove
  705. if($action == 'remove')
  706. {
  707. // executed only if the sql file exists!
  708. return mysql_query("DROP TABLE ".MPREFIX."user_extended_".$field_name) ? true : false;
  709. }
  710. }
  711. function manage_userclass($action, $class_name, $class_description)
  712. {
  713. global $e107;
  714. $tp = e107::getParser();
  715. $sql = e107::getDb();
  716. $mes = e107::getMessage();
  717. $mes->addDebug("Userclass: ".$action.": ".$class_name." : ".$class_description);
  718. if (!$e107->user_class->isAdmin())
  719. {
  720. $e107->user_class = new user_class_admin; // We need the extra methods of the admin extension
  721. }
  722. $class_name = strip_tags(strtoupper($class_name));
  723. if ($action == 'add')
  724. {
  725. if ($e107->user_class->ucGetClassIDFromName($class_name) !== FALSE)
  726. { // Class already exists.
  727. return TRUE; // That's probably OK
  728. }
  729. $i = $e107->user_class->findNewClassID();
  730. if ($i !== FALSE)
  731. {
  732. $tmp = array();
  733. $tmp['userclass_id'] = $i;
  734. $tmp['userclass_name'] = $class_name;
  735. $tmp['userclass_description'] = $class_description;
  736. $tmp['userclass_editclass'] = e_UC_ADMIN;
  737. $tmp['userclass_visibility'] = e_UC_ADMIN;
  738. $tmp['userclass_type'] = UC_TYPE_STD;
  739. $tmp['userclass_parent'] = e_UC_NOBODY;
  740. $tmp['_FIELD_TYPES']['userclass_editclass'] = 'int';
  741. $tmp['_FIELD_TYPES']['userclass_visibility'] = 'int';
  742. $tmp['_FIELD_TYPES']['userclass_id'] = 'int';
  743. $tmp['_FIELD_TYPES']['_DEFAULT'] = 'todb';
  744. return $e107->user_class->add_new_class($tmp);
  745. }
  746. else
  747. {
  748. return NULL;
  749. }
  750. }
  751. if ($action == 'remove')
  752. {
  753. $classID = $e107->user_class->ucGetClassIDFromName($class_name);
  754. if (($classID !== FALSE) && ($e107->user_class->deleteClassAndUsers($classID) === TRUE))
  755. {
  756. return TRUE;
  757. }
  758. else
  759. {
  760. return FALSE;
  761. }
  762. }
  763. }
  764. function manage_link($action, $link_url, $link_name, $link_class = 0, $options=array())
  765. {
  766. $sql = e107::getDb();
  767. $tp = e107::getParser();
  768. if (!is_numeric($link_class))
  769. {
  770. $link_class = strtolower($link_class);
  771. $plug_perm['everyone'] = e_UC_PUBLIC;
  772. $plug_perm['guest'] = e_UC_GUEST;
  773. $plug_perm['member'] = e_UC_MEMBER;
  774. $plug_perm['mainadmin'] = e_UC_MAINADMIN;
  775. $plug_perm['admin'] = e_UC_ADMIN;
  776. $plug_perm['nobody'] = e_UC_NOBODY;
  777. $link_class = ($plug_perm[$link_class]) ? intval($plug_perm[$link_class]) : e_UC_PUBLIC;
  778. }
  779. $link_url = $tp->toDB($link_url, true);
  780. $link_name = $tp->toDB($link_name, true);
  781. $path = str_replace("../", "", $link_url); // This should clean up 'non-standard' links
  782. $path = $tp->createConstants($path); // Add in standard {e_XXXX} directory constants if we can
  783. if ($action == 'add')
  784. {
  785. $link_t = $sql->count('links');
  786. if (!$sql->count('links', '(*)', "WHERE link_url = '{$path}' OR link_name = '{$link_name}'"))
  787. {
  788. $linkData = array(
  789. 'link_name' => $link_name,
  790. 'link_url' => $path,
  791. 'link_description' => '',
  792. 'link_button' => '',
  793. 'link_category' => '1',
  794. 'link_order' => $link_t + 1,
  795. 'link_parent' => '0',
  796. 'link_open' => '0',
  797. 'link_class' => vartrue($linkclass,'0'),
  798. 'link_function' => (vartrue($options['link_function']) ? $this->plugFolder ."::".$options['link_function'] : "")
  799. );
  800. return $sql->insert('links', $linkData); // TODO: Add the _FIELD_DEFS array
  801. }
  802. else
  803. {
  804. return ;
  805. }
  806. }
  807. if ($action == 'remove')
  808. { // Look up by URL if we can - should be more reliable. Otherwise try looking up by name (as previously)
  809. if (($path && $sql->select('links', 'link_id,link_order', "link_url = '{$path}'")) || $sql->select('links', 'link_id,link_order', "link_name = '{$link_name}'"))
  810. {
  811. $row = $sql->fetch();
  812. $sql->db_Update('links', "link_order = link_order - 1 WHERE link_order > {$row['link_order']}");
  813. return $sql->delete('links', "link_id = {$row['link_id']}");
  814. }
  815. }
  816. }
  817. // DEPRECATED in 0.8 - See XmlPrefs(); Left for BC.
  818. // Update prefs array according to $action
  819. // $prefType specifies the storage type - may be 'pref', 'listPref' or 'arrayPref'
  820. function manage_prefs($action, $var, $prefType = 'pref', $path = '', $unEscape = FALSE)
  821. {
  822. global $pref;
  823. if (!is_array($var))
  824. return;
  825. if (($prefType == 'arrayPref') && ($path == ''))
  826. return;
  827. foreach ($var as $k => $v)
  828. {
  829. if ($unEscape)
  830. {
  831. $v = str_replace(array('\{', '\}'), array('{', '}'), $v);
  832. }
  833. switch ($prefType)
  834. {
  835. case 'pref':
  836. switch ($action)
  837. {
  838. case 'add':
  839. $pref[$k] = $v;
  840. break;
  841. case 'update' :
  842. case 'upgrade' :
  843. case 'refresh':
  844. // Only update if $pref doesn't exist
  845. if (!isset($pref[$k]))
  846. $pref[$k] = $v;
  847. break;
  848. case 'remove':
  849. if (is_numeric($k))
  850. { // Sometimes arrays specified with value being the name of the key to delete
  851. unset($pref[$var[$k]]);
  852. }
  853. else
  854. { // This is how the array should be specified - key is the name of the pref
  855. unset($pref[$k]);
  856. }
  857. break;
  858. }
  859. break;
  860. case 'listPref':
  861. $tmp = array();
  862. if (isset($pref[$k]))
  863. $tmp = explode(',', $pref[$k]);
  864. switch ($action)
  865. {
  866. case 'add':
  867. case 'update' :
  868. case 'upgrade' :
  869. case 'refresh':
  870. if (!in_array($v, $tmp))
  871. $tmp[] = $v;
  872. break;
  873. case 'remove':
  874. if (($tkey = array_search($v, $tmp)) !== FALSE)
  875. unset($tmp[$tkey]);
  876. break;
  877. }
  878. $pref[$k] = implode(',', $tmp); // Leaves an empty element if no values - probably acceptable or even preferable
  879. break;
  880. case 'arrayPref':
  881. switch ($action)
  882. {
  883. case 'add':
  884. $pref[$k][$path] = $v;
  885. break;
  886. case 'update' :
  887. case 'upgrade' :
  888. case 'refresh':
  889. if (!isset($pref[$k][$path]))
  890. $pref[$k][$path] = $v;
  891. break;
  892. case 'remove':
  893. if (isset($pref[$k][$path]))
  894. unset($pref[$k][$path]); // Leaves an empty element if no values - probably acceptable or even preferable
  895. break;
  896. }
  897. break;
  898. }
  899. }
  900. e107::getConfig('core')->setPref($pref)->save();
  901. // e107::getConfig()->loadData($pref, false)->save(false, true);
  902. }
  903. function manage_comments($action, $comment_id)
  904. {
  905. $sql = e107::getDb();
  906. $tp = e107::getParser();
  907. $tmp = array();
  908. if ($action == 'remove')
  909. {
  910. foreach ($comment_id as $com)
  911. {
  912. $tmp[] = "comment_type='".$tp->toDB($com, true)."'";
  913. }
  914. $qry = implode(" OR ", $tmp);
  915. // echo $qry."<br />";
  916. return $sql->delete('comments', $qry);
  917. }
  918. }
  919. // Handle table updates - passed an array of actions.
  920. // $var array:
  921. // For 'add' - its a query to create the table
  922. // For 'upgrade' - its a query to modify the table (not called from the plugin.xml handler)
  923. // For 'remove' - its a table name
  924. // 'upgrade' and 'remove' operate on all language variants of the same table
  925. function manage_tables($action, $var)
  926. {
  927. $sql = e107::getDB();
  928. $mes = e107::getMessage();
  929. if (!is_array($var))
  930. return FALSE; // Return if nothing to do
  931. $error = false;
  932. $error_data = array();
  933. switch ($action)
  934. {
  935. case 'add':
  936. foreach ($var as $tab)
  937. {
  938. $tab = str_replace("TYPE=MyISAM","ENGINE=MyISAM",$tab);
  939. if(!preg_match("/MyISAM.*CHARSET ?= ?utf8/i",$tab))
  940. {
  941. $tab = str_replace("MyISAM", "MyISAM DEFAULT CHARSET=utf8", $tab);
  942. }
  943. $mes->addDebug($tab);
  944. if (false === $sql->db_Query($tab))
  945. {
  946. $error = true;
  947. $error_data[] = $tab;
  948. }
  949. }
  950. break;
  951. case 'upgrade':
  952. foreach ($var as $tab)
  953. {
  954. if (false === $sql->db_Query_all($tab))
  955. {
  956. $error = true;
  957. $error_data[] = $tab;
  958. }
  959. }
  960. break;
  961. case 'remove':
  962. foreach ($var as $tab)
  963. {
  964. $qry = 'DROP TABLE '.MPREFIX.$tab;
  965. if (!$sql->db_Query_all($qry))
  966. {
  967. $error = true;
  968. $error_data[] = $tab;
  969. }
  970. }
  971. break;
  972. }
  973. // doesn't exit the loop now, returns true on success
  974. // or error queries (string)
  975. return (!$error ? true : (!empty($$error_data) ? implode('<br />', $error_data) : false));
  976. }
  977. // DEPRECATED for 0.8 xml files - See XmlPrefs();
  978. // Handle prefs from arrays (mostly 0.7 stuff, possibly apart from the special cases)
  979. function manage_plugin_prefs($action, $prefname, $plugin_folder, $varArray = '')
  980. { // These prefs are 'cumulative' - several plugins may contribute an array element
  981. // global $pref;
  982. /*
  983. if ($prefname == 'plug_sc' || $prefname == 'plug_bb')
  984. { // Special cases - shortcodes and bbcodes - each plugin may contribute several elements
  985. foreach($varArray as $code)
  986. {
  987. $prefvals[] = "$code:$plugin_folder";
  988. }
  989. }
  990. else
  991. {
  992. */
  993. $prefvals[] = $varArray;
  994. // $prefvals[] = $plugin_folder;
  995. // }
  996. $curvals = explode(',', $pref[$prefname]);
  997. if ($action == 'add')
  998. {
  999. $newvals = array_merge($curvals, $prefvals);
  1000. }
  1001. if ($action == 'remove')
  1002. {
  1003. foreach ($prefvals as $v)
  1004. {
  1005. if (($i = array_search($v, $curvals)) !== FALSE)
  1006. {
  1007. unset($curvals[$i]);
  1008. }
  1009. }
  1010. $newvals = $curvals;
  1011. }
  1012. $newvals = array_unique($newvals);
  1013. $pref[$prefname] = implode(',', $newvals);
  1014. if (substr($pref[$prefname], 0, 1) == ",")
  1015. {
  1016. $pref[$prefname] = substr($pref[$prefname], 1);
  1017. }
  1018. e107::getConfig('core')->setPref($pref);
  1019. e107::getConfig('core')->save();
  1020. }
  1021. function manage_search($action, $eplug_folder)
  1022. {
  1023. global $sysprefs;
  1024. $sql = e107::getDb();
  1025. $search_prefs = e107::getConfig('search')->getPref();
  1026. // $search_prefs = $sysprefs -> getArray('search_prefs');
  1027. $default = file_exists(e_PLUGIN.$eplug_folder.'/e_search.php') ? TRUE : FALSE;
  1028. $comments = file_exists(e_PLUGIN.$eplug_folder.'/search/search_comments.php') ? TRUE : FALSE;
  1029. if ($action == 'add')
  1030. {
  1031. $install_default = $default ? TRUE : FALSE;
  1032. $install_comments = $comments ? TRUE : FALSE;
  1033. }
  1034. else
  1035. if ($action == 'remove')
  1036. {
  1037. $uninstall_default = isset($search_prefs['plug_handlers'][$eplug_folder]) ? TRUE : FALSE;
  1038. $uninstall_comments = isset($search_prefs['comments_handlers'][$eplug_folder]) ? TRUE : FALSE;
  1039. }
  1040. else
  1041. if ($action == 'upgrade')
  1042. {
  1043. if (isset($search_prefs['plug_handlers'][$eplug_folder]))
  1044. {
  1045. $uninstall_default = $default ? FALSE : TRUE;
  1046. }
  1047. else
  1048. {
  1049. $install_default = $default ? TRUE : FALSE;
  1050. }
  1051. if (isset($search_prefs['comments_handlers'][$eplug_folder]))
  1052. {
  1053. $uninstall_comments = $comments ? FALSE : TRUE;
  1054. }
  1055. else
  1056. {
  1057. $install_comments = $comments ? TRUE : FALSE;
  1058. }
  1059. }
  1060. if (vartrue($install_default))
  1061. {
  1062. $search_prefs['plug_handlers'][$eplug_folder] = array('class' => 0, 'pre_title' => 1, 'pre_title_alt' => '', 'chars' => 150, 'results' => 10);
  1063. }
  1064. else
  1065. if (vartrue($uninstall_default))
  1066. {
  1067. unset($search_prefs['plug_handlers'][$eplug_folder]);
  1068. }
  1069. if (vartrue($install_comments))
  1070. {
  1071. require_once(e_PLUGIN.$eplug_folder.'/search/search_comments.php');
  1072. $search_prefs['comments_handlers'][$eplug_folder] = array('id' => $comments_type_id, 'class' => 0, 'dir' => $eplug_folder);
  1073. }
  1074. else
  1075. if (vartrue($uninstall_comments))
  1076. {
  1077. unset($search_prefs['comments_handlers'][$eplug_folder]);
  1078. }
  1079. e107::getConfig('search')->setPref($search_prefs)->save();
  1080. }
  1081. function manage_notify($action, $eplug_folder)
  1082. {
  1083. $tp = e107::getParser();
  1084. // $notify_prefs = $sysprefs -> get('notify_prefs');
  1085. // $notify_prefs = $eArrayStorage -> ReadArray($notify_prefs);
  1086. $notify_prefs = e107::getConfig('notify');
  1087. $e_notify = file_exists(e_PLUGIN.$eplug_folder.'/e_notify.php') ? TRUE : FALSE;
  1088. if ($action == 'add')
  1089. {
  1090. $install_notify = $e_notify ? TRUE : FALSE;
  1091. }
  1092. else
  1093. if ($action == 'remove')
  1094. {
  1095. $uninstall_notify = $notify_prefs->isData('plugins/'.$eplug_folder); //isset($notify_prefs['plugins'][$eplug_folder]) ? TRUE : FALSE;
  1096. }
  1097. else
  1098. if ($action == 'upgrade')
  1099. {
  1100. if ($notify_prefs->isData('plugins/'.$eplug_folder))
  1101. {
  1102. $uninstall_notify = $e_notify ? FALSE : TRUE;
  1103. }
  1104. else
  1105. {
  1106. $install_notify = $e_notify ? TRUE : FALSE;
  1107. }
  1108. }
  1109. if (vartrue($install_notify))
  1110. {
  1111. $notify_prefs->setPref('plugins/'.$eplug_folder, 1); //$notify_prefs['plugins'][$eplug_folder] = TRUE;
  1112. require_once(e_PLUGIN.$eplug_folder.'/e_notify.php');
  1113. foreach ($config_events as $event_id => $event_text)
  1114. {
  1115. $notify_prefs->setPref('event/'.$event_id.'/class', e_UC_NOBODY)
  1116. ->setPref('event/'.$event_id.'/email', '');
  1117. //$notify_prefs['event'][$event_id] = array('class' => e_UC_NOBODY, 'email' => '');
  1118. }
  1119. }
  1120. else
  1121. if (vartrue($uninstall_notify))
  1122. {
  1123. $notify_prefs->removePref('plugins/'.$eplug_folder);
  1124. //unset($notify_prefs['plugins'][$eplug_folder]);
  1125. require_once(e_PLUGIN.$eplug_folder.'/e_notify.php');
  1126. foreach ($config_events as $event_id => $event_text)
  1127. {
  1128. $notify_prefs->removePref('event/'.$event_id);
  1129. //unset($notify_prefs['event'][$event_id]);
  1130. }
  1131. }
  1132. //$s_prefs = $tp -> toDB($notify_prefs);
  1133. //$s_prefs = e107::getArrayStorage()->WriteArray($s_prefs);
  1134. //e107::getDb() -> db_Update("core", "e107_value='".$s_prefs."' WHERE e107_name='notify_prefs'");
  1135. $notify_prefs->save(false);
  1136. }
  1137. /**
  1138. * Rebuild URL configuration values
  1139. * Note - new core system pref values will be set, but not saved
  1140. * e107::getConfig()->save() is required outside after execution of this method
  1141. * @return void
  1142. */
  1143. public function rebuildUrlConfig()
  1144. {
  1145. $modules = eRouter::adminReadModules(); // get all available locations, non installed plugins will be ignored
  1146. $config = eRouter::adminBuildConfig(e107::getPref('url_config'), $modules); // merge with current config
  1147. $locations = eRouter::adminBuildLocations($modules); // rebuild locations pref
  1148. $aliases = eRouter::adminSyncAliases(e107::getPref('url_aliases'), $config); // rebuild aliases
  1149. // set new values, changes should be saved outside this methods
  1150. e107::getConfig()
  1151. ->set('url_aliases', $aliases)
  1152. ->set('url_config', $config)
  1153. ->set('url_modules', $modules)
  1154. ->set('url_locations', $locations);
  1155. eRouter::clearCache();
  1156. }
  1157. function displayArray(&$array, $msg = '')
  1158. {
  1159. $txt = ($msg ? $msg.'<br />' : '');
  1160. foreach ($array as $_k => $_v)
  1161. {
  1162. $txt .= "{$_k} -> {$_v}<br />";
  1163. }
  1164. $txt .= '<br />';
  1165. return $txt;
  1166. }
  1167. /**
  1168. * Install routine for XML file
  1169. * @param object $id (the number of the plugin in the DB) or the path to the plugin folder. eg. 'forum'
  1170. * @param object $function install|upgrade|uninstall|refresh (adds things that are missing, but doesn't change any existing settings)
  1171. * @param object $options [optional] an array of possible options - ATM used only for uninstall:
  1172. * 'delete_userclasses' - to delete userclasses created
  1173. * 'delete_tables' - to delete DB tables
  1174. * 'delete_xfields' - to delete extended fields
  1175. * 'delete_ipool' - to delete icon pool entry
  1176. * + any defined in <pluginname>_setup.php in the uninstall_options() method.
  1177. * @return TBD
  1178. */
  1179. function install_plugin_xml($id, $function = '', $options = FALSE)
  1180. {
  1181. $pref = e107::getPref();
  1182. $sql = e107::getDb();
  1183. $mes = e107::getMessage();
  1184. $error = array(); // Array of error messages
  1185. $canContinue = TRUE; // Clear flag if must abort part way through
  1186. if(is_array($id))
  1187. {
  1188. $plug = $id;
  1189. $id = $plug['plugin_id'];
  1190. }
  1191. else
  1192. {
  1193. $id = (int) $id;
  1194. $plug = $this->getinfo($id); // Get plugin info from DB
  1195. }
  1196. $this->current_plug = $plug;
  1197. $txt = '';
  1198. $path = e_PLUGIN.$plug['plugin_path'].'/';
  1199. $this->plugFolder = $plug['plugin_path'];
  1200. $this->unInstallOpts = $options;
  1201. $addons = explode(',', $plug['plugin_addons']);
  1202. $sql_list = array();
  1203. foreach ($addons as $addon)
  1204. {
  1205. if (substr($addon, -4) == '_sql')
  1206. {
  1207. $sql_list[] = $addon.'.php';
  1208. }
  1209. }
  1210. if (!file_exists($path.'plugin.xml') || $function == '')
  1211. {
  1212. $error[] = EPL_ADLAN_77;
  1213. $canContinue = FALSE;
  1214. }
  1215. if ($canContinue && $this->parse_plugin_xml($plug['plugin_path']))
  1216. {
  1217. $plug_vars = $this->plug_vars;
  1218. }
  1219. else
  1220. {
  1221. $error[] = EPL_ADLAN_76;
  1222. $canContinue = FALSE;
  1223. }
  1224. // Load install language file and set lan_global pref.
  1225. $this->XmlLanguageFiles($function, $plug_vars['languageFiles'], 'pre'); // First of all, see if there's a language file specific to install
  1226. // Next most important, if installing or upgrading, check that any dependencies are met
  1227. if ($canContinue && ($function != 'uninstall') && isset($plug_vars['dependencies']))
  1228. {
  1229. $canContinue = $this->XmlDependencies($plug_vars['dependencies']);
  1230. }
  1231. if (!$canContinue)
  1232. {
  1233. return FALSE;
  1234. }
  1235. // All the dependencies are OK - can start the install now
  1236. if ($canContinue) // Run custom {plugin}_setup install/upgrade etc. for INSERT, ALTER etc. etc. etc.
  1237. {
  1238. $ret = $this->execute_function($plug['plugin_path'], $function, 'pre');
  1239. if (!is_bool($ret))
  1240. $txt .= $ret;
  1241. }
  1242. // Handle tables
  1243. if ($canContinue && count($sql_list)) // TODO - move to it's own function. XmlTables().
  1244. {
  1245. require_once(e_HANDLER.'db_table_admin_class.php');
  1246. $dbHandler = new db_table_admin;
  1247. foreach ($sql_list as $sqlFile)
  1248. {
  1249. $tableList = $dbHandler->get_table_def('', $path.$sqlFile);
  1250. if (!is_array($tableList))
  1251. {
  1252. $mes->addError("Can't read SQL definition: ".$path.$sqlFile);
  1253. break;
  1254. }
  1255. // Got the required definition here
  1256. foreach ($tableList as $ct)
  1257. { // Process one table at a time (but they could be multi-language)
  1258. switch ($function)
  1259. {
  1260. case 'install':
  1261. $sqlTable = str_replace("CREATE TABLE ".MPREFIX.'`', "CREATE TABLE `".MPREFIX, preg_replace("/create table\s+/si", "CREATE TABLE ".MPREFIX, $ct[0]));
  1262. $txt = "Adding Table: {$ct[1]} ... ";
  1263. $status = $this->manage_tables('add', array($sqlTable)) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; // Pass the statement to create the table
  1264. $mes->add($txt, $status);
  1265. break;
  1266. case 'upgrade':
  1267. $tmp = $dbHandler->update_table_structure($ct, FALSE, TRUE, $pref['multilanguage']);
  1268. if ($tmp === FALSE)
  1269. {
  1270. $error[] = 'Error Updating Table: '.$ct[1];
  1271. }
  1272. elseif ($tmp !== TRUE)
  1273. {
  1274. $error[] = $tmp;
  1275. }
  1276. break;
  1277. case 'refresh': // Leave things alone
  1278. break;
  1279. case 'uninstall':
  1280. if (vartrue($options['delete_tables'], FALSE))
  1281. {
  1282. $txt = "Removing Table: {$ct[1]} <br />";
  1283. $status = $this->manage_tables('remove', array($ct[1])) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR; // Delete the table
  1284. $mes->add($txt, $status);
  1285. }
  1286. else
  1287. {
  1288. $mes->addSuccess("Table {$ct[1]} left in place.");
  1289. }
  1290. break;
  1291. }
  1292. }
  1293. }
  1294. }
  1295. if (varset($plug_vars['adminLinks']))
  1296. {
  1297. $this->XmlAdminLinks($function, $plug_vars['adminLinks']);
  1298. }
  1299. if (varset($plug_vars['siteLinks']))
  1300. {
  1301. $this->XmlSiteLinks($function, $plug_vars['siteLinks']);
  1302. }
  1303. if (varset($plug_vars['mainPrefs'])) //Core pref items <mainPrefs>
  1304. {
  1305. $this->XmlPrefs('core', $function, $plug_vars['mainPrefs']);
  1306. }
  1307. if (varset($plug_vars['pluginPrefs'])) //Plugin pref items <pluginPrefs>
  1308. {
  1309. $this->XmlPrefs($plug['plugin_path'], $function, $plug_vars['pluginPrefs']);
  1310. }
  1311. if (varset($plug_vars['userClasses']))
  1312. {
  1313. $this->XmlUserClasses($function, $plug_vars['userClasses']);
  1314. }
  1315. if (varset($plug_vars['extendedFields']))
  1316. {
  1317. $this->XmlExtendedFields($function, $plug_vars['extendedFields']);
  1318. }
  1319. if (varset($plug_vars['languageFiles']))
  1320. {
  1321. $this->XmlLanguageFiles($function, $plug_vars['languageFiles']);
  1322. }
  1323. if (varset($plug_vars['bbcodes']))
  1324. {
  1325. $this->XmlBBcodes($function, $plug_vars);
  1326. }
  1327. if (varset($plug_vars['mediaCategories']))
  1328. {
  1329. $this->XmlMediaCategories($function, $plug_vars);
  1330. }
  1331. $this->manage_icons($this->plugFolder, $function);
  1332. //FIXME
  1333. //If any commentIDs are configured, we need to remove all comments on uninstall
  1334. if ($function == 'uninstall' && isset($plug_vars['commentID']))
  1335. {
  1336. $txt .= 'Removing all plugin comments: ('.implode(', ', $plug_vars['commentID']).')<br />';
  1337. $this->manage_comments('remove', $commentArray);
  1338. }
  1339. $this->manage_search($function, $plug_vars['folder']);
  1340. $this->manage_notify($function, $plug_vars['folder']);
  1341. $eplug_addons = $this->getAddons($plug['plugin_path']);
  1342. $p_installed = e107::getPref('plug_installed', array()); // load preference;
  1343. if ($function == 'install' || $function == 'upgrade' || $function == 'refresh')
  1344. {
  1345. $sql->update('plugin', "plugin_installflag = 1, plugin_addons = '{$eplug_addons}', plugin_version = '{$plug_vars['@attributes']['version']}', plugin_category ='".$this->manage_category($plug_vars['category'])."' WHERE plugin_id = ".$id);
  1346. $p_installed[$plug['plugin_path']] = $plug_vars['@attributes']['version'];
  1347. e107::getConfig('core')->setPref('plug_installed', $p_installed);
  1348. //e107::getConfig('core')->save(); - save triggered below
  1349. }
  1350. if ($function == 'uninstall')
  1351. {
  1352. $sql->update('plugin', "plugin_installflag = 0, plugin_addons = '{$eplug_addons}', plugin_version = '{$plug_vars['@attributes']['version']}', plugin_category ='".$this->manage_category($plug_vars['category'])."' WHERE plugin_id = ".$id);
  1353. unset($p_installed[$plug['plugin_path']]);
  1354. e107::getConfig('core')->setPref('plug_installed', $p_installed);
  1355. }
  1356. e107::getMessage()->addDebug("updated Installed plugins pref: ".print_a($p_installed,true));
  1357. $this->rebuildUrlConfig();
  1358. e107::getConfig('core')->save();
  1359. /* if($function == 'install')
  1360. {
  1361. if(isset($plug_vars['management']['installDone'][0]))
  1362. {
  1363. $mes->add($plug_vars['management']['installDone'][0], E_MESSAGE_SUCCESS);
  1364. }
  1365. }*/
  1366. // Run custom {plugin}_setup install/upgrade etc. for INSERT, ALTER etc. etc. etc.
  1367. // Call any custom post functions defined in <plugin>_setup.php or the deprecated <management> section
  1368. if (!$this->execute_function($plug['plugin_path'], $function, 'post'))
  1369. {
  1370. if ($function == 'install')
  1371. {
  1372. $text = "Installation Complete.";
  1373. if ($this->plugConfigFile)
  1374. {
  1375. $text .= "<br /><a class='btn btn-primary' href='".$this->plugConfigFile."'>".LAN_CONFIGURE."</a>";
  1376. }
  1377. $mes->addSuccess($text);
  1378. }
  1379. }
  1380. }
  1381. // Placeholder.
  1382. function XmlTables($data)
  1383. {
  1384. }
  1385. /**
  1386. * Process XML Tag <dependencies> (deprecated 'depend' which is a brand of adult diapers)
  1387. * @param array $tag
  1388. * @return boolean
  1389. */
  1390. function XmlDependencies($tag)
  1391. {
  1392. $canContinue = TRUE;
  1393. $mes = e107::getMessage();
  1394. $error = array();
  1395. foreach ($tag as $dt => $dv)
  1396. {
  1397. if (isset($dv['@attributes']) && isset($dv['@attributes']['name']))
  1398. {
  1399. // echo "Check {$dt} dependency: {$dv['@attributes']['name']} version {$dv['@attributes']['min_version']}<br />";
  1400. switch ($dt)
  1401. {
  1402. case 'plugin':
  1403. if (!isset($pref['plug_installed'][$dv['@attributes']['name']]))
  1404. { // Plugin not installed
  1405. $canContinue = FALSE;
  1406. $error[] = EPL_ADLAN_70.$dv['@attributes']['name'];
  1407. }
  1408. elseif (isset($dv['@attributes']['min_version']) && (version_compare($dv['@attributes']['min_version'], $pref['plug_installed'][$dv['@attributes']['name']], '<=') === FALSE))
  1409. {
  1410. $error[] = EPL_ADLAN_71.$dv['@attributes']['name'].EPL_ADLAN_72.$dv['@attributes']['min_version'];
  1411. $canContinue = FALSE;
  1412. }
  1413. break;
  1414. case 'extension':
  1415. if (!extension_loaded($dv['@attributes']['name']))
  1416. {
  1417. $canContinue = FALSE;
  1418. $error[] = EPL_ADLAN_73.$dv['@attributes']['name'];
  1419. }
  1420. elseif (isset($dv['@attributes']['min_version']) && (version_compare($dv['@attributes']['min_version'], phpversion($dv['@attributes']['name']), '<=') === FALSE))
  1421. {
  1422. $error[] = EPL_ADLAN_71.$dv['@attributes']['name'].EPL_ADLAN_72.$dv['@attributes']['min_version'];
  1423. $canContinue = FALSE;
  1424. }
  1425. break;
  1426. case 'php': // all should be lowercase
  1427. if (isset($dv['@attributes']['min_version']) && (version_compare($dv['@attributes']['min_version'], phpversion(), '<=') === FALSE))
  1428. {
  1429. $error[] = EPL_ADLAN_74.$dv['@attributes']['min_version'];
  1430. $canContinue = FALSE;
  1431. }
  1432. break;
  1433. case 'mysql': // all should be lowercase
  1434. if (isset($dv['@attributes']['min_version']) && (version_compare($dv['@attributes']['min_version'], mysql_get_server_info(), '<=') === FALSE))
  1435. {
  1436. $error[] = EPL_ADLAN_75.$dv['@attributes']['min_version'];
  1437. $canContinue = FALSE;
  1438. }
  1439. break;
  1440. default:
  1441. echo "Unknown dependency: {$dt}<br />";
  1442. }
  1443. }
  1444. }
  1445. if (count($error))
  1446. {
  1447. $text = '<b>'.LAN_INSTALL_FAIL.'</b><br />'.implode('<br />', $error);
  1448. $mes->addError($text);
  1449. }
  1450. return $canContinue;
  1451. }
  1452. /**
  1453. * Look for a language file in the two acceptable places.
  1454. * If found, update the appropriate pref
  1455. *
  1456. * @param string $fileEnd - the suffix of the file name (e.g. '_global')
  1457. * @param string $prefName - the name of the pref to be updated
  1458. * @param string $when = install|upgrade|refresh|uninstall ('update' also supported as alias for 'upgrade')
  1459. * @param string $isInstalled - flag indicates whether plugin installed
  1460. * - if false, any preference is removed.
  1461. * - if TRUE, any preference is added
  1462. * - so set TRUE to add value to pref regardless
  1463. * @param boolean $justPath
  1464. * - if TRUE, plugin name is written to pref, as a generic string which requires a search to locate the file.
  1465. * - if FALSE, a precise path within the plugin folder, which includes '--LAN--' strings to substitute for language, is written
  1466. * @param string $plugin - name of plugin folder. If empty string, $this->plugFolder is used (may not always exist).
  1467. *
  1468. * @return boolean TRUE if pref changed
  1469. */
  1470. public function XmlLanguageFileCheck($fileEnd, $prefName, $when, $isInstalled, $justPath = FALSE, $plugin = '')
  1471. {
  1472. $core = e107::getConfig('core');
  1473. $mes = e107::getMessage();
  1474. if (trim($plugin) == '') $plugin = $this->plugFolder;
  1475. if (!$plugin) return FALSE; // No plugin name - error
  1476. if (!$isInstalled) $when = 'uninstall';
  1477. $updated = false;
  1478. $path_a = e_PLUGIN.$plugin.'/languages/English'.$fileEnd.'.php'; // always check for English so we have a fall-back
  1479. $path_b = e_PLUGIN.$plugin.'/languages/English/English'.$fileEnd.'.php';
  1480. $pathEntry = '';
  1481. if (file_exists($path_a))
  1482. {
  1483. $pathEntry = $justPath ? $plugin : '--LAN--'.$fileEnd.'.php';
  1484. }
  1485. elseif (file_exists($path_b))
  1486. {
  1487. $pathEntry = $justPath ? $plugin : '--LAN--/--LAN--'.$fileEnd.'.php';
  1488. }
  1489. $currentPref = $core->getPref($prefName.'/'.$plugin);
  1490. //echo 'Path: '.$plugin.' Pref: '.$prefName.' Current: '.$currentPref.' New: '.$pathEntry.'<br />';
  1491. switch ($when)
  1492. {
  1493. case 'install':
  1494. case 'upgrade':
  1495. case 'update' :
  1496. case 'refresh':
  1497. if ($currentPref != $pathEntry)
  1498. {
  1499. $mes->addDebug('Adding '.$plugin.' to '.$prefName);
  1500. $core->setPref($prefName.'/'.$plugin, $pathEntry);
  1501. $updated = true;
  1502. }
  1503. break;
  1504. case 'uninstall':
  1505. if ($currentPref)
  1506. {
  1507. $mes->addDebug('Removing '.$plugin.' from '.$prefName);
  1508. $core->removePref($prefName.'/'.$plugin);
  1509. $updated = true;
  1510. }
  1511. break;
  1512. }
  1513. return $updated;
  1514. }
  1515. /**
  1516. * Process XML Tag <LanguageFiles> // Tag is DEPRECATED - using _install _log and _global
  1517. * @param object $function - should $when have been used?
  1518. * @param object $tag (not used?)
  1519. * @param string $when = install|upgrade|refresh|uninstall
  1520. * @return none
  1521. */
  1522. function XmlLanguageFiles($function, $tag='', $when = '')
  1523. {
  1524. $core = e107::getConfig('core');
  1525. $updated = false;
  1526. $path_a = e_PLUGIN.$this->plugFolder."/languages/English_install.php"; // always check for English so we have a fall-back
  1527. $path_b = e_PLUGIN.$this->plugFolder."/languages/English/English_install.php";
  1528. if(file_exists($path_a) || file_exists($path_b))
  1529. {
  1530. e107::lan($this->plugFolder,'install',true);
  1531. }
  1532. $path_a = e_PLUGIN.$this->plugFolder."/languages/English_global.php"; // always check for English so we have a fall-back
  1533. $path_b = e_PLUGIN.$this->plugFolder."/languages/English/English_global.php";
  1534. if(file_exists($path_a) || file_exists($path_b))
  1535. {
  1536. switch ($function)
  1537. {
  1538. case 'install':
  1539. case 'upgrade':
  1540. case 'refresh':
  1541. e107::getMessage()->addDebug("Adding ".$this->plugFolder." to lan_global_list");
  1542. e107::lan($this->plugFolder,'global',true);
  1543. $core->setPref('lan_global_list/'.$this->plugFolder, $this->plugFolder);
  1544. $updated = true;
  1545. break;
  1546. case 'uninstall':
  1547. $core->removePref('lan_global_list/'.$this->plugFolder);
  1548. $update = true;
  1549. break;
  1550. }
  1551. }
  1552. $path_a = e_PLUGIN.$this->plugFolder."/languages/English_log.php"; // always check for English so we have a fall-back
  1553. $path_b = e_PLUGIN.$this->plugFolder."/languages/English/English_log.php";
  1554. if(file_exists($path_a) || file_exists($path_b))
  1555. {
  1556. switch ($function)
  1557. {
  1558. case 'install':
  1559. case 'upgrade':
  1560. case 'refresh':
  1561. $core->setPref('lan_log_list/'.$this->plugFolder, $this->plugFolder);
  1562. $updated = true;
  1563. break;
  1564. case 'uninstall':
  1565. $core->removePref('lan_log_list/'.$this->plugFolder);
  1566. $updated = true;
  1567. break;
  1568. }
  1569. }
  1570. if($updated === true)
  1571. {
  1572. $core->save(); //FIXME do this quietly without an s-message
  1573. }
  1574. }
  1575. /**
  1576. * Process XML Tag <siteLinks>
  1577. * @param string $function install|upgrade|refresh|uninstall
  1578. * @param array $array
  1579. * @return none
  1580. */
  1581. function XmlSiteLinks($function, $array)
  1582. {
  1583. $mes = e107::getMessage();
  1584. if(vartrue($this->options['nolinks']))
  1585. {
  1586. return;
  1587. }
  1588. foreach ($array['link'] as $link)
  1589. {
  1590. $attrib = $link['@attributes'];
  1591. $linkName = (defset($link['@value'])) ? constant($link['@value']) : $link['@value'];
  1592. $remove = (varset($attrib['deprecate']) == 'true') ? TRUE : FALSE;
  1593. $url = vartrue($attrib['url']);
  1594. $perm = vartrue($attrib['perm'],'everyone');
  1595. $options = array(
  1596. 'link_function'=>vartrue($attrib['function'])
  1597. );
  1598. switch ($function)
  1599. {
  1600. case 'upgrade':
  1601. case 'install':
  1602. if (!$remove) // Add any non-deprecated link
  1603. {
  1604. $result = $this->manage_link('add', $url, $linkName, $perm, $options);
  1605. if($result !== NULL)
  1606. {
  1607. $status = ($result) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1608. $mes->add("Adding Link: {$linkName} with url [{$url}] and perm {$perm} ", $status);
  1609. }
  1610. }
  1611. if ($function == 'upgrade' && $remove) //remove inactive links on upgrade
  1612. {
  1613. $status = ($this->manage_link('remove', $url, $linkName,false, $options)) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1614. $mes->add("Removing Link: {$linkName} with url [{$url}]", $status);
  1615. }
  1616. break;
  1617. case 'refresh': // Probably best to leave well alone
  1618. break;
  1619. case 'uninstall': //remove all links
  1620. $status = ($this->manage_link('remove', $url, $linkName)) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1621. $mes->add("Removing Link: {$linkName} with url [{$url}]", $status);
  1622. break;
  1623. }
  1624. }
  1625. }
  1626. /**
  1627. * Process XML Tag <adminLinks>
  1628. * @return none
  1629. */
  1630. function XmlAdminLinks($function, $tag)
  1631. {
  1632. foreach ($tag['link'] as $link)
  1633. {
  1634. $attrib = $link['@attributes'];
  1635. $linkName = (defset($link['@value'])) ? constant($link['@value']) : $link['@value'];
  1636. $url = e_PLUGIN_ABS.$this->plugFolder."/".$attrib['url'];
  1637. if (isset($attrib['primary']) && $attrib['primary'] == 'true')
  1638. {
  1639. $this->plugConfigFile = $url;
  1640. }
  1641. }
  1642. }
  1643. // Only 1 category per file-type allowed. ie. 1 for images, 1 for files.
  1644. function XmlMediaCategories($function, $tag)
  1645. {
  1646. $mes = e107::getMessage();
  1647. // print_a($tag);
  1648. $folder = $tag['folder'];
  1649. $prevType = "";
  1650. //print_a($tag);
  1651. switch ($function)
  1652. {
  1653. case 'install':
  1654. $c = 1;
  1655. foreach($tag['mediaCategories']['category'] as $v)
  1656. {
  1657. $type = $v['@attributes']['type'];
  1658. if(strpos($type, 'image') !== 0 && strpos($type, 'file') !== 0 && strpos($type, 'video') !== 0)
  1659. {
  1660. continue;
  1661. }
  1662. if($c == 4 || ($prevType == $type))
  1663. {
  1664. $mes->addDebug("Only 3 Media Categories are permitted during install. One for images and one for files.");
  1665. break;
  1666. }
  1667. $prevType = $type;
  1668. $data['owner'] = $folder;
  1669. $data['image'] = vartrue($v['@attributes']['image']);
  1670. $data['category'] = $folder."_".$type;
  1671. $data['title'] = $v['@value'];
  1672. $data['sef'] = vartrue($v['@attributes']['sef']);
  1673. // $data['type'] = $v['@attributes']['type']; //TODO
  1674. $data['class'] = 253;
  1675. $status = e107::getMedia()->createCategory($data) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1676. $mes->add("Adding Media Category: {$data['category']}", $status);
  1677. e107::getMedia()->import($data['category'],e_PLUGIN.$folder, false,'min-size=20000');
  1678. $c++;
  1679. }
  1680. break;
  1681. case 'uninstall': // Probably best to leave well alone
  1682. $status = e107::getMedia()->deleteAllCategories($folder)? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1683. $mes->add("Deleting All Media Categories owned by : {$folder}", $status);
  1684. break;
  1685. }
  1686. }
  1687. /**
  1688. * Process XML Tag <bbcodes>
  1689. * @return none
  1690. */
  1691. function XmlBBcodes($function, $tag)
  1692. {
  1693. $mes = e107::getMessage();
  1694. //print_a($tag);
  1695. switch ($function)
  1696. {
  1697. case 'install': // Probably best to leave well alone
  1698. if(vartrue($tag['bbcodes']['@attributes']['imgResize']))
  1699. {
  1700. e107::getConfig('core')->setPref('resize_dimensions/'.$this->plugFolder."-bbcode", array('w'=>300,'h'=>300));
  1701. $mes->debug('Adding imageResize for: '.$this->plugFolder);
  1702. }
  1703. break;
  1704. case 'uninstall': // Probably best to leave well alone
  1705. if(vartrue($tag['bbcodes']['@attributes']['imgResize']))
  1706. {
  1707. //e107::getConfig('core')->removePref('resize_dimensions/'.$this->plugFolder);
  1708. //e107::getConfig('core')->removePref('e_imageresize/'.$this->plugFolder);
  1709. e107::getConfig('core')->removePref('resize_dimensions/'.$this->plugFolder."-bbcode");
  1710. $mes->debug('Removing imageResize for: '.$this->plugFolder."-bbcode");
  1711. }
  1712. break;
  1713. }
  1714. return;
  1715. }
  1716. /**
  1717. * Process XML Tag <userClasses>
  1718. * @param string $function install|upgrade|refresh|uninstall
  1719. * @param array $array
  1720. * @return none
  1721. */
  1722. function XmlUserClasses($function, $array)
  1723. {
  1724. $mes = e107::getMessage();
  1725. foreach ($array['class'] as $uclass)
  1726. {
  1727. $attrib = $uclass['@attributes'];
  1728. $name = $attrib['name'];
  1729. $description = $attrib['description'];
  1730. $remove = (varset($attrib['deprecate']) == 'true') ? TRUE : FALSE;
  1731. switch ($function)
  1732. {
  1733. case 'install':
  1734. case 'upgrade':
  1735. case 'refresh':
  1736. if (!$remove) // Add all active userclasses (code checks for already installed)
  1737. {
  1738. $result = $this->manage_userclass('add', $name, $description);
  1739. if($result !== NULL)
  1740. {
  1741. $status = ($result) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1742. $mes->add('Adding Userclass: '.$name, $status);
  1743. }
  1744. }
  1745. if ($function == 'upgrade' && $remove) //If upgrading, removing any inactive userclass
  1746. {
  1747. $status = $this->manage_userclass('remove', $name, $description) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1748. $mes->add('Removing Userclass: '.$name, $status);
  1749. }
  1750. break;
  1751. case 'uninstall': //If uninstalling, remove all userclasses (active or inactive)
  1752. if (varsettrue($this->unInstallOpts['delete_userclasses'], FALSE))
  1753. {
  1754. $status = $this->manage_userclass('remove', $name, $description) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1755. $mes->add('Removing Userclass: '.$name, $status);
  1756. }
  1757. else
  1758. {
  1759. $mes->add('Userclass: '.$name.' left in place'.$name, $status);
  1760. }
  1761. break;
  1762. }
  1763. }
  1764. }
  1765. /**
  1766. * Process XML Tag <extendedFields>
  1767. * @param string $function install|upgrade|refresh|uninstall
  1768. * @param array $array
  1769. * @return none
  1770. */
  1771. function XmlExtendedFields($function, $array)
  1772. {
  1773. $mes = e107::getMessage();
  1774. $this->setUe();
  1775. foreach ($array['field'] as $efield)
  1776. {
  1777. $attrib = $efield['@attributes'];
  1778. $attrib['default'] = varset($attrib['default']);
  1779. $type = $this->ue_field_type($attrib);
  1780. $name = $this->ue_field_name($this->plugFolder, $type, $attrib['name']);
  1781. //$name = 'plugin_'.$this->plugFolder.'_'.$attrib['name'];
  1782. $source = 'plugin_'.$this->plugFolder;
  1783. $remove = (varset($attrib['deprecate']) == 'true') ? TRUE : FALSE;
  1784. if(!isset($attrib['system'])) $attrib['system'] = true; // default true
  1785. else $attrib['system'] = $attrib['system'] === 'true' ? true : false;
  1786. switch ($function)
  1787. {
  1788. case 'install': // Add all active extended fields
  1789. case 'upgrade':
  1790. if (!$remove)
  1791. {
  1792. //$status = $this->manage_extended_field('add', $name, $type, $attrib['default'], $source) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1793. $status = $this->manage_extended_field('add', $name, $attrib, $source) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1794. $mes->add('Adding Extended Field: '.$name.' ... ', $status);
  1795. }
  1796. if ($function == 'upgrade' && $remove) //If upgrading, removing any inactive extended fields
  1797. {
  1798. $status = $this->manage_extended_field('remove', $name, $attrib, $source) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1799. $mes->add('Removing Extended Field: '.$name.' ... ', $status);
  1800. }
  1801. break;
  1802. case 'uninstall': //If uninstalling, remove all extended fields (active or inactive)
  1803. if (varsettrue($this->unInstallOpts['delete_xfields'], FALSE))
  1804. {
  1805. $status = ($this->manage_extended_field('remove', $name, $attrib, $source)) ? E_MESSAGE_SUCCESS : E_MESSAGE_ERROR;
  1806. $mes->add('Removing Extended Field: '.$name.' ... ', $status);
  1807. }
  1808. else
  1809. {
  1810. $mes->add('Extended Field: '.$name.' left in place'.$name, E_MESSAGE_SUCCESS);
  1811. }
  1812. break;
  1813. }
  1814. }
  1815. }
  1816. /**
  1817. * Process XML tags <mainPrefs> and <pluginPrefs>
  1818. * @param object $mode 'core' or the folder name of the plugin.
  1819. * @param object $function install|uninstall|upgrade|refresh
  1820. * @param object $prefArray XML array of prefs. eg. mainPref() or pluginPref();
  1821. * @return none
  1822. */
  1823. function XmlPrefs($mode = 'core', $function, $prefArray)
  1824. {
  1825. //XXX Could also be used for theme prefs.. perhaps this function should be moved elsewhere?
  1826. //TODO array support for prefs. <key>? or array() as used in xml site export?
  1827. $mes = e107::getMessage();
  1828. if (!varset($prefArray) || !varset($prefArray))
  1829. {
  1830. return;
  1831. }
  1832. $config = ($mode == 'core') ? e107::getConfig('core') : e107::getPlugConfig($mode);
  1833. foreach ($prefArray['pref'] as $tag)
  1834. {
  1835. $key = varset($tag['@attributes']['name']);
  1836. $value = vartrue($tag['@value']);
  1837. if(substr($value,0,5) == "e_UC_") // Convert Userclass constants.
  1838. {
  1839. $value = constant($value);
  1840. }
  1841. $remove = (varset($tag['@attributes']['deprecate']) == 'true') ? TRUE : FALSE;
  1842. if (varset($tag['@attributes']['value']))
  1843. {
  1844. $mes->addError("Deprecated plugin.xml spec. found. Use the following format: ".htmlentities("<pref name='name'>value</pref>"));
  1845. }
  1846. switch ($function)
  1847. {
  1848. case 'install':
  1849. case 'upgrade':
  1850. $ret = $config->add($key, $value);
  1851. if($ret->data_has_changed == TRUE)
  1852. {
  1853. $mes->addSuccess("Adding Pref: ".$key);
  1854. }
  1855. break;
  1856. case 'refresh':
  1857. if ($remove) // remove active='false' prefs.
  1858. {
  1859. $config->remove($key, $value);
  1860. $mes->addSuccess("Removing Pref: ".$key);
  1861. }
  1862. else
  1863. {
  1864. $config->update($key, $value);
  1865. $mes->addSuccess("Updating Pref: ".$key);
  1866. }
  1867. break;
  1868. case 'uninstall':
  1869. $config->remove($key, $value);
  1870. $mes->addSuccess("Removing Pref: ".$key);
  1871. break;
  1872. }
  1873. }
  1874. if ($mode != "core") // Do only one core pref save during install/uninstall etc.
  1875. {
  1876. $config->save();
  1877. }
  1878. return;
  1879. }
  1880. /**
  1881. *
  1882. * @param object $path [unused]
  1883. * @param object $what install|uninstall|upgrade
  1884. * @param object $when pre|post
  1885. * @param array $callbackData callback method arguments
  1886. * @return boolean FALSE
  1887. */
  1888. function execute_function($path = null, $what = '', $when = '', $callbackData = null)
  1889. {
  1890. $mes = e107::getMessage();
  1891. if($path == null)
  1892. {
  1893. $path = $this->plugFolder;
  1894. }
  1895. $class_name = $path."_setup"; // was using $this->pluginFolder;
  1896. $method_name = $what."_".$when;
  1897. // {PLUGIN}_setup.php should ALWAYS be the name of the file..
  1898. // if (varset($this->plug_vars['@attributes']['setupFile']))
  1899. // {
  1900. // $setup_file = e_PLUGIN.$this->plugFolder.'/'.$this->plug_vars['@attributes']['setupFile'];
  1901. // }
  1902. // else
  1903. // {
  1904. $setup_file = e_PLUGIN.$path.'/'.$path.'_setup.php';
  1905. // }
  1906. if (is_readable($setup_file))
  1907. {
  1908. if(e_PAGE == 'e107_update.php' && E107_DBG_INCLUDES)
  1909. {
  1910. $mes->addDebug("Found setup file <b>".$path."_setup.php</b> ");
  1911. }
  1912. include_once($setup_file);
  1913. if (class_exists($class_name))
  1914. {
  1915. $obj = new $class_name;
  1916. $obj->version_from = $this;
  1917. if (method_exists($obj, $method_name))
  1918. {
  1919. if(e_PAGE == 'e107_update.php' && E107_DBG_INCLUDES)
  1920. {
  1921. $mes->addDebug("Executing setup function <b>".$class_name." :: ".$method_name."()</b>");
  1922. }
  1923. if(null !== $callbackData) return call_user_func_array(array($obj, $method_name), $callbackData);
  1924. return call_user_func(array($obj, $method_name), $this);
  1925. }
  1926. else
  1927. {
  1928. if(e_PAGE == 'e107_update.php' && E107_DBG_INCLUDES)
  1929. {
  1930. $mes->addDebug("Setup function ".$class_name." :: ".$method_name."() NOT found.");
  1931. }
  1932. return FALSE;
  1933. }
  1934. }
  1935. else
  1936. {
  1937. // $mes->add("Setup Class ".$class_name." NOT found.", E_MESSAGE_DEBUG);
  1938. return FALSE;
  1939. }
  1940. }
  1941. else
  1942. {
  1943. //$mes->add("Optional Setup File NOT Found ".$path."_setup.php ", E_MESSAGE_DEBUG);
  1944. }
  1945. return FALSE; // IMPORTANT.
  1946. }
  1947. // DEPRECATED - See XMLPrefs();
  1948. function parse_prefs($pref_array, $mode = 'simple')
  1949. {
  1950. $ret = array();
  1951. if (!isset($pref_array[0]))
  1952. {
  1953. $pref_array = array($pref_array);
  1954. }
  1955. if (is_array($pref_array))
  1956. {
  1957. foreach ($pref_array as $k => $p)
  1958. {
  1959. $attrib = $p['@attributes'];
  1960. if (isset($attrib['type']) && $attrib['type'] == 'array')
  1961. {
  1962. $name = $attrib['name'];
  1963. $tmp = $this->parse_prefs($pref_array[$k]['key']);
  1964. $ret['all'][$name] = $tmp['all'];
  1965. $ret['active'][$name] = $tmp['active'];
  1966. $ret['inactive'][$name] = $tmp['inactive'];
  1967. }
  1968. else
  1969. {
  1970. $ret['all'][$attrib['name']] = $attrib['value'];
  1971. if (!isset($attrib['active']) || $attrib['active'] == 'true')
  1972. {
  1973. $ret['active'][$attrib['name']] = $attrib['value'];
  1974. }
  1975. else
  1976. {
  1977. $ret['inactive'][$attrib['name']] = $attrib['value'];
  1978. }
  1979. }
  1980. }
  1981. }
  1982. return $ret;
  1983. }
  1984. function install_plugin_php($id)
  1985. {
  1986. $function = 'install';
  1987. $sql = e107::getDb();
  1988. $mes = e107::getMessage();
  1989. $mySQLprefix = MPREFIX; // Fix for some plugin.php files.
  1990. if(is_array($id))
  1991. {
  1992. $plug = $id;
  1993. $id = $plug['plugin_id'];
  1994. }
  1995. else
  1996. {
  1997. $plug = $this->getinfo($id);
  1998. }
  1999. $_path = e_PLUGIN.$plug['plugin_path'].'/';
  2000. $plug['plug_action'] = 'install';
  2001. $this->parse_plugin_php($plug['plugin_path']);
  2002. $plug_vars = $this->plug_vars;
  2003. include($_path.'plugin.php');
  2004. $func = $eplug_folder.'_install';
  2005. if (function_exists($func))
  2006. {
  2007. $text .= call_user_func($func);
  2008. }
  2009. if (is_array($eplug_tables))
  2010. {
  2011. $result = $this->manage_tables('add', $eplug_tables);
  2012. if ($result === TRUE)
  2013. {
  2014. $text .= EPL_ADLAN_19.'<br />';
  2015. $mes->addSuccess(EPL_ADLAN_19);
  2016. }
  2017. else
  2018. {
  2019. $mes->addError(EPL_ADLAN_18);
  2020. }
  2021. }
  2022. /* if (is_array($eplug_prefs))
  2023. {
  2024. $this->manage_prefs('add', $eplug_prefs);
  2025. $text .= EPL_ADLAN_8.'<br />';
  2026. }*/
  2027. if (varset($plug_vars['mainPrefs'])) //Core pref items <mainPrefs>
  2028. {
  2029. $this->XmlPrefs('core', $function, $plug_vars['mainPrefs']);
  2030. $text .= EPL_ADLAN_8.'<br />';
  2031. }
  2032. if (is_array($eplug_array_pref))
  2033. {
  2034. foreach ($eplug_array_pref as $key => $val)
  2035. {
  2036. $this->manage_plugin_prefs('add', $key, $eplug_folder, $val);
  2037. }
  2038. }
  2039. if (varset($plug_vars['siteLinks']))
  2040. {
  2041. $this->XmlSiteLinks($function, $plug_vars['siteLinks']);
  2042. }
  2043. if (varset($plug_vars['userClasses']))
  2044. {
  2045. $this->XmlUserClasses($function, $plug_vars['userClasses']);
  2046. }
  2047. $this->manage_search('add', $eplug_folder);
  2048. $this->manage_notify('add', $eplug_folder);
  2049. $eplug_addons = $this->getAddons($eplug_folder);
  2050. $sql->update('plugin', "plugin_installflag = 1, plugin_addons = '{$eplug_addons}' WHERE plugin_id = ".(int) $id);
  2051. $p_installed = e107::getPref('plug_installed', array()); // load preference;
  2052. $p_installed[$plug['plugin_path']] = $plug['plugin_version'];
  2053. e107::getConfig('core')->setPref('plug_installed', $p_installed);
  2054. $this->rebuildUrlConfig();
  2055. e107::getConfig('core')->save();
  2056. $text .= (isset($eplug_done) ? "<br />{$eplug_done}" : "<br />".LAN_INSTALL_SUCCESSFUL);
  2057. if ($eplug_conffile)
  2058. {
  2059. $text .= "<br /><a class='btn btn-primary' href='".e_PLUGIN.$eplug_folder."/".$eplug_conffile."'>".LAN_CONFIGURE."</a>";
  2060. }
  2061. return $text;
  2062. }
  2063. /**
  2064. * BC Alias for install();
  2065. */
  2066. public function install_plugin($id)
  2067. {
  2068. global $sysprefs, $mySQLprefix;
  2069. return $this->install($id);
  2070. }
  2071. /**
  2072. * Refresh Plugin Info, Install flag, e_xxx, ignore existing tables. etc.
  2073. *
  2074. * @param int $dir - plugin folder.
  2075. */
  2076. function refresh($dir)
  2077. {
  2078. if(empty($dir))
  2079. {
  2080. return;
  2081. }
  2082. global $sysprefs, $mySQLprefix;
  2083. $ns = e107::getRender();
  2084. $sql = e107::getDb();
  2085. $tp = e107::getParser();
  2086. $plug = $this->getinfo($dir);
  2087. $this->options = array('nolinks'=>true);
  2088. if(!is_array($plug))
  2089. {
  2090. return "'{$id}' is missing from the plugin db table";
  2091. }
  2092. $_path = e_PLUGIN.$plug['plugin_path'].'/';
  2093. if (file_exists($_path.'plugin.xml'))
  2094. {
  2095. $text = $this->install_plugin_xml($plug, 'refresh');
  2096. }
  2097. else
  2098. {
  2099. $text = EPL_ADLAN_21;
  2100. }
  2101. $this->save_addon_prefs();
  2102. return $text;
  2103. }
  2104. /**
  2105. * Installs a plugin by ID or folder name
  2106. *
  2107. * @param int $id
  2108. * @param array $options (currently only 'nolinks' - set to true to prevent sitelink creation during install)
  2109. */
  2110. function install($id, $options = array())
  2111. {
  2112. global $sysprefs, $mySQLprefix;
  2113. $ns = e107::getRender();
  2114. $sql = e107::getDb();
  2115. $tp = e107::getParser();
  2116. $this->options = $options;
  2117. $text = '';
  2118. // install plugin ...
  2119. $plug = $this->getinfo($id);
  2120. if(!is_array($plug))
  2121. {
  2122. return "'{$id}' is missing from the plugin db table";
  2123. }
  2124. $plug['plug_action'] = 'install';
  2125. if (!vartrue($plug['plugin_installflag']))
  2126. {
  2127. $_path = e_PLUGIN.$plug['plugin_path'].'/';
  2128. if (file_exists($_path.'plugin.xml'))
  2129. {
  2130. $text = $this->install_plugin_xml($plug, 'install');
  2131. }
  2132. elseif (file_exists($_path.'plugin.php'))
  2133. {
  2134. $text = $this->install_plugin_php($plug);
  2135. }
  2136. }
  2137. else
  2138. {
  2139. $text = EPL_ADLAN_21;
  2140. }
  2141. return $text;
  2142. }
  2143. /*
  2144. * scan the plugin table and create path-array-prefs for each addon.
  2145. *
  2146. * @param string $mode = install|upgrade|refresh|uninstall - defines the intent of the call
  2147. *
  2148. * 'upgrade' and 'refresh' are very similar in intent, and often take the same actions:
  2149. * 'upgrade' signals a possible change to the installed list of plugins - usually an upgrade
  2150. * 'refresh' validates the stored data for existing plugins, recreating any that has gone missing
  2151. */
  2152. function save_addon_prefs($mode = 'upgrade')
  2153. {
  2154. $sql = e107::getDb();
  2155. $core = e107::getConfig('core');
  2156. foreach ($this->plugin_addons as $var) // clear all existing prefs.
  2157. {
  2158. $core->update($var.'_list', "");
  2159. }
  2160. // reset
  2161. $core->set('bbcode_list', array())
  2162. ->set('shortcode_legacy_list', array())
  2163. ->set('shortcode_list', array());
  2164. $query = "SELECT * FROM #plugin WHERE plugin_addons !='' ORDER BY plugin_path ASC";
  2165. if ($sql->gen($query))
  2166. {
  2167. while ($row = $sql->fetch())
  2168. {
  2169. $is_installed = ($row['plugin_installflag'] == 1);
  2170. $tmp = explode(",", $row['plugin_addons']);
  2171. $path = $row['plugin_path'];
  2172. if ($is_installed)
  2173. {
  2174. foreach ($tmp as $val)
  2175. {
  2176. if (strpos($val, 'e_') === 0)
  2177. {
  2178. // $addpref[$val."_list"][$path] = $path;
  2179. $core->setPref($val.'_list/'.$path, $path);
  2180. }
  2181. }
  2182. }
  2183. // search for .bb and .sc files.
  2184. $scl_array = array();
  2185. $sc_array = array();
  2186. $bb_array = array();
  2187. $sql_array = array();
  2188. foreach ($tmp as $adds)
  2189. {
  2190. // legacy shortcodes - plugin root *.sc files
  2191. if (substr($adds, -3) === ".sc")
  2192. {
  2193. $sc_name = substr($adds, 0, -3); // remove the .sc
  2194. if ($is_installed)
  2195. {
  2196. $scl_array[$sc_name] = "0"; // default userclass = e_UC_PUBLIC
  2197. }
  2198. else
  2199. {
  2200. $scl_array[$sc_name] = e_UC_NOBODY; // register shortcode, but disable it
  2201. }
  2202. }
  2203. // new shortcodes location - shortcodes/single/*.php
  2204. elseif (substr($adds, 0, 3) === "sc_")
  2205. {
  2206. $sc_name = substr(substr($adds, 3), 0, -4); // remove the sc_ and .php
  2207. if ($is_installed)
  2208. {
  2209. $sc_array[$sc_name] = "0"; // default userclass = e_UC_PUBLIC
  2210. }
  2211. else
  2212. {
  2213. $sc_array[$sc_name] = e_UC_NOBODY; // register shortcode, but disable it
  2214. }
  2215. }
  2216. if($is_installed)
  2217. {
  2218. // simple bbcode
  2219. if(substr($adds,-3) == ".bb")
  2220. {
  2221. $bb_name = substr($adds, 0,-3); // remove the .bb
  2222. $bb_array[$bb_name] = "0"; // default userclass.
  2223. }
  2224. // bbcode class
  2225. elseif(substr($adds, 0, 3) == "bb_" && substr($adds, -4) == ".php")
  2226. {
  2227. $bb_name = substr($adds, 0,-4); // remove the .php
  2228. $bb_name = substr($bb_name, 3);
  2229. $bb_array[$bb_name] = "0"; // TODO - instance and getPermissions() method
  2230. }
  2231. }
  2232. if ($is_installed && (substr($adds, -4) == "_sql"))
  2233. {
  2234. $core->setPref('e_sql_list/'.$path, $adds);
  2235. }
  2236. }
  2237. // Build Bbcode list (will be empty if plugin not installed)
  2238. if (count($bb_array) > 0)
  2239. {
  2240. ksort($bb_array);
  2241. $core->setPref('bbcode_list/'.$path, $bb_array);
  2242. }
  2243. // Build shortcode list - do if uninstalled as well
  2244. if (count($scl_array) > 0)
  2245. {
  2246. ksort($scl_array);
  2247. $core->setPref('shortcode_legacy_list/'.$path, $scl_array);
  2248. }
  2249. if (count($sc_array) > 0)
  2250. {
  2251. ksort($sc_array);
  2252. $core->setPref('shortcode_list/'.$path, $sc_array);
  2253. }
  2254. }
  2255. }
  2256. $core->save(FALSE);
  2257. if ($this->manage_icons())
  2258. {
  2259. // echo 'IT WORKED';
  2260. }
  2261. else
  2262. {
  2263. // echo "didn't work!";
  2264. }
  2265. return;
  2266. }
  2267. // return a list of available plugin addons for the specified plugin. e_xxx etc.
  2268. // $debug = TRUE - prints diagnostics
  2269. // $debug = 'check' - checks each file found for php tags - prints 'pass' or 'fail'
  2270. function getAddons($plugin_path, $debug = FALSE)
  2271. {
  2272. $fl = e107::getFile();
  2273. $mes = e107::getMessage();
  2274. $p_addons = array();
  2275. foreach ($this->plugin_addons as $addon) //Find exact matches only.
  2276. {
  2277. // if(preg_match("#^(e_.*)\.php$#", $f['fname'], $matches))
  2278. $addonPHP = $addon.".php";
  2279. if (is_readable(e_PLUGIN.$plugin_path."/".$addonPHP))
  2280. {
  2281. if ($debug === 'check')
  2282. {
  2283. $passfail = '';
  2284. $file_text = file_get_contents(e_PLUGIN.$plugin_path."/".$addonPHP);
  2285. if ((substr($file_text, 0, 5) != '<'.'?php') || ((substr($file_text, -2, 2) != '?'.'>') && (strrpos($file_text, '?'.'>') !== FALSE)))
  2286. {
  2287. $passfail = '<b>fail</b>';
  2288. }
  2289. else
  2290. {
  2291. $passfail = 'pass';
  2292. }
  2293. echo $plugin_path."/".$addon.".php - ".$passfail."<br />";
  2294. }
  2295. // $mes->add('Detected addon: <b>'.$addon.'</b>', E_MESSAGE_DEBUG);
  2296. $p_addons[] = $addon;
  2297. }
  2298. }
  2299. // Grab List of Shortcodes & BBcodes
  2300. $shortcodeLegacyList = $fl->get_files(e_PLUGIN.$plugin_path, '\.sc$', "standard", 1);
  2301. $shortcodeList = $fl->get_files(e_PLUGIN.$plugin_path.'/shortcodes/single', '\.php$', "standard", 1);
  2302. $bbcodeList = $fl->get_files(e_PLUGIN.$plugin_path, '\.bb$', "standard", 1);
  2303. $bbcodeClassList= $fl->get_files(e_PLUGIN.$plugin_path, '^bb_(.*)\.php$', "standard", 1);
  2304. $bbcodeList = array_merge($bbcodeList, $bbcodeClassList);
  2305. $sqlList = $fl->get_files(e_PLUGIN.$plugin_path, '_sql\.php$', "standard", 1);
  2306. // Search Shortcodes
  2307. foreach ($shortcodeLegacyList as $sc)
  2308. {
  2309. if (is_readable(e_PLUGIN.$plugin_path."/".$sc['fname']))
  2310. {
  2311. $p_addons[] = $sc['fname'];
  2312. }
  2313. }
  2314. foreach ($shortcodeList as $sc)
  2315. {
  2316. if (is_readable(e_PLUGIN.$plugin_path."/shortcodes/single/".$sc['fname']))
  2317. {
  2318. $p_addons[] = 'sc_'.$sc['fname'];
  2319. }
  2320. }
  2321. // Search Bbcodes.
  2322. foreach ($bbcodeList as $bb)
  2323. {
  2324. if (is_readable(e_PLUGIN.$plugin_path."/".$bb['fname']))
  2325. {
  2326. $p_addons[] = $bb['fname'];
  2327. }
  2328. }
  2329. // Search _sql files.
  2330. foreach ($sqlList as $esql)
  2331. {
  2332. if (is_readable(e_PLUGIN.$plugin_path."/".$esql['fname']))
  2333. {
  2334. $fname = str_replace(".php", "", $esql['fname']);
  2335. if (!in_array($fname, $p_addons))
  2336. $p_addons[] = $fname; // Probably already found - avoid duplication
  2337. }
  2338. }
  2339. if ($debug == true)
  2340. {
  2341. echo $plugin_path." = ".implode(",", $p_addons)."<br />";
  2342. }
  2343. return implode(",", $p_addons);
  2344. }
  2345. /**
  2346. * Check Plugin Addon for errors.
  2347. * @return array or numeric. 0 = OK, 1 = Fail, 2 = inaccessible
  2348. */
  2349. function checkAddon($plugin_path, $e_xxx)
  2350. {
  2351. if (is_readable(e_PLUGIN.$plugin_path."/".$e_xxx.".php"))
  2352. {
  2353. $content = file_get_contents(e_PLUGIN.$plugin_path."/".$e_xxx.".php");
  2354. }
  2355. else
  2356. {
  2357. return 2;
  2358. }
  2359. if(substr($e_xxx, - 4, 4) == '_sql')
  2360. {
  2361. if(strpos($content,'INSERT INTO')!==false)
  2362. {
  2363. return array('type'=> 'error', 'msg'=>"INSERT sql commands are not permitted here. Use a ".$plugin_path."_setup.php file instead.");
  2364. }
  2365. else
  2366. {
  2367. return 0;
  2368. }
  2369. }
  2370. // Generic markup check
  2371. if ((substr($content, 0, 5) != '<'.'?php') || ((substr($content, -2, 2) != '?'.'>') && (strrpos($content, '?'.'>') !== FALSE)))
  2372. {
  2373. return 1;
  2374. }
  2375. if($e_xxx == 'e_meta' && strpos($content,'<script')!==false)
  2376. {
  2377. return array('type'=> 'warning', 'msg'=>"Contains script tags. Use e_header.php with the e107::js() function instead.");
  2378. }
  2379. if($e_xxx == 'e_latest' && strpos($content,'<div')!==false)
  2380. {
  2381. return array('type'=> 'warning', 'msg'=>"Using deprecated method. See e_latest.php in the forum plugin for an example.");
  2382. }
  2383. if($e_xxx == 'e_status' && strpos($content,'<div')!==false)
  2384. {
  2385. return array('type'=> 'warning', 'msg'=>"Using deprecated method. See e_status.php in the forum plugin for an example.");
  2386. }
  2387. return 0;
  2388. }
  2389. // Entry point to read plugin configuration data
  2390. function parse_plugin($plugName, $force = false)
  2391. {
  2392. $ret = "";
  2393. if (isset($this->parsed_plugin[$plugName]) && $force != true)
  2394. {
  2395. $this->plug_vars = $this->parsed_plugin[$plugName];
  2396. return true;
  2397. }
  2398. unset($this->parsed_plugin[$plugName]); // In case forced parsing which fails
  2399. if (file_exists(e_PLUGIN.$plugName.'/plugin.xml'))
  2400. {
  2401. $ret = $this->parse_plugin_xml($plugName);
  2402. }
  2403. elseif (file_exists(e_PLUGIN.$plugName.'/plugin.php'))
  2404. {
  2405. $ret = $this->parse_plugin_php($plugName);
  2406. }
  2407. if ($ret == true)
  2408. {
  2409. $this->parsed_plugin[$plugName] = $this->plug_vars;
  2410. }
  2411. return $ret;
  2412. }
  2413. // return the Icon of the
  2414. function getIcon($plugName='',$size=32)
  2415. {
  2416. if(!$plugName) return;
  2417. $tp = e107::getParser();
  2418. if(!isset($this->parsed_plugin[$plugName]))
  2419. {
  2420. $plug_vars = $this->parse_plugin($plugName);
  2421. }
  2422. else
  2423. {
  2424. $plug_vars = $this->parsed_plugin[$plugName];
  2425. }
  2426. //return print_r($plug_vars,TRUE);
  2427. $sizeArray = array(32=>'icon', 16=>'iconSmall');
  2428. $default = ($size == 32) ? $tp->toGlyph('e-cat_plugins-32') : "<img class='icon S16' src='".E_16_CAT_PLUG."' alt='' />";
  2429. $sz = $sizeArray[$size];
  2430. $icon_src = e_PLUGIN.$plugName."/".$plug_vars['administration'][$sz];
  2431. $plugin_icon = $plug_vars['administration'][$sz] ? "<img src='{$icon_src}' alt='' class='icon S".intval($size)."' />" : $default;
  2432. if(!$plugin_icon)
  2433. {
  2434. //
  2435. }
  2436. return $plugin_icon;
  2437. }
  2438. // Called to parse the (deprecated) plugin.php file
  2439. function parse_plugin_php($plugName)
  2440. {
  2441. $mes = e107::getMessage();
  2442. $tp = e107::getParser();
  2443. if (include(e_PLUGIN.$plugName.'/plugin.php'))
  2444. {
  2445. //$mes->add("Loading ".e_PLUGIN.$plugName.'/plugin.php', E_MESSAGE_DEBUG);
  2446. }
  2447. $ret = array();
  2448. // $ret['installRequired'] = ($eplug_conffile || is_array($eplug_table_names) || is_array($eplug_prefs) || is_array($eplug_sc) || is_array($eplug_bb) || $eplug_module || $eplug_userclass || $eplug_status || $eplug_latest);
  2449. $ret['@attributes']['name'] = varset($eplug_name);
  2450. $ret['@attributes']['lang'] = varset($eplug_name);
  2451. $ret['@attributes']['version'] = varset($eplug_version);
  2452. $ret['@attributes']['date'] = varset($eplug_date);
  2453. $ret['@attributes']['compatibility'] = varset($eplug_compatible);
  2454. $ret['@attributes']['installRequired'] = ($eplug_conffile || is_array($eplug_table_names) || is_array($eplug_prefs) || $eplug_module || $eplug_userclass || $eplug_status || $eplug_latest) ? 'true' : '';
  2455. $ret['@attributes']['xhtmlcompliant'] = vartrue($eplug_compliant) ? 'true' : '';
  2456. $ret['folder'] = (varset($eplug_folder)) ? $eplug_folder : $plugName;
  2457. $ret['author']['@attributes']['name'] = varset($eplug_author);
  2458. $ret['author']['@attributes']['url'] = varset($eplug_url);
  2459. $ret['author']['@attributes']['email'] = varset($eplug_email);
  2460. $ret['description']['@value'] = varset($eplug_description);
  2461. $ret['description']['@attributes']['lang'] = varset($eplug_description);
  2462. $ret['category'] = varset($eplug_category) ? $this->manage_category($eplug_category) : "misc";
  2463. $ret['readme'] = varset($eplug_readme);
  2464. $ret['menuName'] = varset($eplug_menu_name);
  2465. if (varset($eplug_prefs))
  2466. {
  2467. $c = 0;
  2468. foreach ($eplug_prefs as $name => $value)
  2469. {
  2470. $ret['mainPrefs']['pref'][$c]['@attributes']['name'] = $name;
  2471. $ret['mainPrefs']['pref'][$c]['@value'] = $value;
  2472. $c++;
  2473. }
  2474. }
  2475. // For BC.
  2476. $ret['administration']['icon'] = str_replace($plugName."/","",$eplug_icon);
  2477. $ret['administration']['caption'] = varset($eplug_caption);
  2478. $ret['administration']['iconSmall'] = str_replace($plugName."/","",$eplug_icon_small);
  2479. $ret['administration']['configFile'] = varset($eplug_conffile);
  2480. if (varset($eplug_conffile))
  2481. {
  2482. $ret['adminLinks']['link'][0]['@attributes']['url'] = varset($eplug_conffile);
  2483. $ret['adminLinks']['link'][0]['@attributes']['description'] = LAN_CONFIGURE;
  2484. $ret['adminLinks']['link'][0]['@attributes']['icon'] = str_replace($plugName."/","",$eplug_icon);
  2485. $ret['adminLinks']['link'][0]['@attributes']['iconSmall'] = str_replace($plugName."/","",$eplug_icon_small);
  2486. $ret['adminLinks']['link'][0]['@attributes']['primary'] = 'true';
  2487. }
  2488. if (vartrue($eplug_link) && varset($eplug_link_name) && varset($eplug_link_url))
  2489. {
  2490. $ret['siteLinks']['link'][0]['@attributes']['url'] = $tp->createConstants($eplug_link_url, 1);
  2491. $ret['siteLinks']['link'][0]['@attributes']['perm'] = varset($eplug_link_perms);
  2492. $ret['siteLinks']['link'][0]['@value'] = varset($eplug_link_name);
  2493. }
  2494. if (vartrue($eplug_userclass) && vartrue($eplug_userclass_description))
  2495. {
  2496. $ret['userClasses']['class'][0]['@attributes']['name'] = $eplug_userclass;
  2497. $ret['userClasses']['class'][0]['@attributes']['description'] = $eplug_userclass_description;
  2498. }
  2499. // Set this key so we know the vars came from a plugin.php file
  2500. // $ret['plugin_php'] = true; // Should no longer be needed.
  2501. $this->plug_vars = $ret;
  2502. return true;
  2503. }
  2504. // Called to parse the plugin.xml file if it exists
  2505. function parse_plugin_xml($plugName, $where = null)
  2506. {
  2507. $tp = e107::getParser();
  2508. // loadLanFiles($plugName, 'admin'); // Look for LAN files on default paths
  2509. $xml = e107::getXml();
  2510. $mes = e107::getMessage();
  2511. // $xml->setOptArrayTags('extendedField,userclass,menuLink,commentID'); // always arrays for these tags.
  2512. // $xml->setOptStringTags('install,uninstall,upgrade');
  2513. if(null === $where) $where = 'plugin.xml';
  2514. $this->plug_vars = $xml->loadXMLfile(e_PLUGIN.$plugName.'/'.$where, 'advanced');
  2515. if ($this->plug_vars === FALSE)
  2516. {
  2517. $mes->addError("Error reading {$plugName}/plugin.xml");
  2518. return FALSE;
  2519. }
  2520. $this->plug_vars['category'] = (isset($this->plug_vars['category'])) ? $this->manage_category($this->plug_vars['category']) : "misc";
  2521. $this->plug_vars['folder'] = $plugName; // remove the need for <folder> tag in plugin.xml.
  2522. if(varset($this->plug_vars['description']))
  2523. {
  2524. if (is_array($this->plug_vars['description']))
  2525. {
  2526. if (isset($this->plug_vars['description']['@attributes']['lan']) && defined($this->plug_vars['description']['@attributes']['lan']))
  2527. {
  2528. // Pick up the language-specific description if it exists.
  2529. $this->plug_vars['description']['@value'] = constant($this->plug_vars['description']['@attributes']['lan']);
  2530. }
  2531. }
  2532. else
  2533. {
  2534. $diz = $this->plug_vars['description'];
  2535. unset($this->plug_vars['description']);
  2536. $this->plug_vars['description']['@value'] = $diz;
  2537. }
  2538. }
  2539. // Very useful debug code.to compare plugin.php vs plugin.xml
  2540. /*
  2541. $testplug = 'forum';
  2542. if($plugName == $testplug)
  2543. {
  2544. $plug_vars1 = $this->plug_vars;
  2545. $this->parse_plugin_php($testplug);
  2546. $plug_vars2 = $this->plug_vars;
  2547. ksort($plug_vars2);
  2548. ksort($plug_vars1);
  2549. echo "<table>
  2550. <tr><td><h1>PHP</h1></td><td><h1>XML</h1></td></tr>
  2551. <tr><td style='border-right:1px solid black'>";
  2552. print_a($plug_vars2);
  2553. echo "</td><td>";
  2554. print_a($plug_vars1);
  2555. echo "</table>";
  2556. }
  2557. */
  2558. // TODO search for $this->plug_vars['adminLinks']['link'][0]['@attributes']['primary']==true.
  2559. $this->plug_vars['administration']['icon'] = varset($this->plug_vars['adminLinks']['link'][0]['@attributes']['icon']);
  2560. $this->plug_vars['administration']['caption'] = varset($this->plug_vars['adminLinks']['link'][0]['@attributes']['description']);
  2561. $this->plug_vars['administration']['iconSmall'] = varset($this->plug_vars['adminLinks']['link'][0]['@attributes']['iconSmall']);
  2562. $this->plug_vars['administration']['configFile'] = varset($this->plug_vars['adminLinks']['link'][0]['@attributes']['url']);
  2563. return TRUE;
  2564. }
  2565. }
  2566. ?>