Plugins.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059
  1. <?php
  2. namespace Elgg\Database;
  3. use Exception;
  4. /**
  5. * @var array cache used by elgg_get_plugins_provides function
  6. * @todo move it with all other functions to \Elgg\PluginsService
  7. */
  8. global $ELGG_PLUGINS_PROVIDES_CACHE;
  9. /**
  10. * Persistent, installation-wide key-value storage.
  11. *
  12. * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
  13. *
  14. * @access private
  15. *
  16. * @package Elgg.Core
  17. * @subpackage Database
  18. * @since 1.10.0
  19. */
  20. class Plugins {
  21. /**
  22. * @var string[] Active plugin IDs with IDs as the array keys. Missing keys imply inactive plugins.
  23. */
  24. protected $active_ids = array();
  25. /**
  26. * @var bool Has $active_ids been populated?
  27. */
  28. protected $active_ids_known = false;
  29. /**
  30. * @var \Elgg\Cache\MemoryPool
  31. */
  32. protected $plugins_by_id;
  33. /**
  34. * Constructor
  35. *
  36. * @param \Elgg\EventsService $events Events service
  37. * @param \Elgg\Cache\MemoryPool $pool Cache for referencing plugins by ID
  38. */
  39. public function __construct(\Elgg\EventsService $events, \Elgg\Cache\MemoryPool $pool) {
  40. $this->plugins_by_id = $pool;
  41. }
  42. /**
  43. * Returns a list of plugin directory names from a base directory.
  44. *
  45. * @param string $dir A dir to scan for plugins. Defaults to config's plugins_path.
  46. * Must have a trailing slash.
  47. *
  48. * @return array Array of directory names (not full paths)
  49. * @access private
  50. */
  51. function getDirsInDir($dir = null) {
  52. if (!$dir) {
  53. $dir = elgg_get_plugins_path();
  54. }
  55. $plugin_dirs = array();
  56. $handle = opendir($dir);
  57. if ($handle) {
  58. while ($plugin_dir = readdir($handle)) {
  59. // must be directory and not begin with a .
  60. if (substr($plugin_dir, 0, 1) !== '.' && is_dir($dir . $plugin_dir)) {
  61. $plugin_dirs[] = $plugin_dir;
  62. }
  63. }
  64. }
  65. sort($plugin_dirs);
  66. return $plugin_dirs;
  67. }
  68. /**
  69. * Discovers plugins in the plugins_path setting and creates \ElggPlugin
  70. * entities for them if they don't exist. If there are plugins with entities
  71. * but not actual files, will disable the \ElggPlugin entities and mark as inactive.
  72. * The \ElggPlugin object holds config data, so don't delete.
  73. *
  74. * @return bool
  75. * @access private
  76. */
  77. function generateEntities() {
  78. $mod_dir = elgg_get_plugins_path();
  79. $db_prefix = elgg_get_config('dbprefix');
  80. // ignore access in case this is called with no admin logged in - needed for creating plugins perhaps?
  81. $old_ia = elgg_set_ignore_access(true);
  82. // show hidden entities so that we can enable them if appropriate
  83. $old_access = access_get_show_hidden_status();
  84. access_show_hidden_entities(true);
  85. $options = array(
  86. 'type' => 'object',
  87. 'subtype' => 'plugin',
  88. 'selects' => array('plugin_oe.*'),
  89. 'joins' => array("JOIN {$db_prefix}objects_entity plugin_oe on plugin_oe.guid = e.guid"),
  90. 'limit' => ELGG_ENTITIES_NO_VALUE,
  91. );
  92. $known_plugins = elgg_get_entities_from_relationship($options);
  93. /* @var \ElggPlugin[] $known_plugins */
  94. if (!$known_plugins) {
  95. $known_plugins = array();
  96. }
  97. // map paths to indexes
  98. $id_map = array();
  99. foreach ($known_plugins as $i => $plugin) {
  100. // if the ID is wrong, delete the plugin because we can never load it.
  101. $id = $plugin->getID();
  102. if (!$id) {
  103. $plugin->delete();
  104. unset($known_plugins[$i]);
  105. continue;
  106. }
  107. $id_map[$plugin->getID()] = $i;
  108. }
  109. $physical_plugins = _elgg_get_plugin_dirs_in_dir($mod_dir);
  110. if (!$physical_plugins) {
  111. return false;
  112. }
  113. // check real plugins against known ones
  114. foreach ($physical_plugins as $plugin_id) {
  115. // is this already in the db?
  116. if (array_key_exists($plugin_id, $id_map)) {
  117. $index = $id_map[$plugin_id];
  118. $plugin = $known_plugins[$index];
  119. // was this plugin deleted and its entity disabled?
  120. if (!$plugin->isEnabled()) {
  121. $plugin->enable();
  122. $plugin->deactivate();
  123. $plugin->setPriority('last');
  124. }
  125. // remove from the list of plugins to disable
  126. unset($known_plugins[$index]);
  127. } else {
  128. // create new plugin
  129. // priority is forced to last in save() if not set.
  130. $plugin = new \ElggPlugin($mod_dir . $plugin_id);
  131. $plugin->save();
  132. }
  133. }
  134. // everything remaining in $known_plugins needs to be disabled
  135. // because they are entities, but their dirs were removed.
  136. // don't delete the entities because they hold settings.
  137. foreach ($known_plugins as $plugin) {
  138. if ($plugin->isActive()) {
  139. $plugin->deactivate();
  140. }
  141. // remove the priority.
  142. $name = _elgg_namespace_plugin_private_setting('internal', 'priority');
  143. remove_private_setting($plugin->guid, $name);
  144. if ($plugin->isEnabled()) {
  145. $plugin->disable();
  146. }
  147. }
  148. access_show_hidden_entities($old_access);
  149. elgg_set_ignore_access($old_ia);
  150. _elgg_reindex_plugin_priorities();
  151. return true;
  152. }
  153. /**
  154. * Cache a reference to this plugin by its ID
  155. *
  156. * @param \ElggPlugin $plugin
  157. *
  158. * @access private
  159. */
  160. function cache(\ElggPlugin $plugin) {
  161. $this->plugins_by_id->put($plugin->getID(), $plugin);
  162. }
  163. /**
  164. * Returns an \ElggPlugin object with the path $path.
  165. *
  166. * @param string $plugin_id The id (dir name) of the plugin. NOT the guid.
  167. * @return \ElggPlugin|null
  168. */
  169. function get($plugin_id) {
  170. return $this->plugins_by_id->get($plugin_id, function () use ($plugin_id) {
  171. $plugin_id = sanitize_string($plugin_id);
  172. $db_prefix = get_config('dbprefix');
  173. $options = array(
  174. 'type' => 'object',
  175. 'subtype' => 'plugin',
  176. 'joins' => array("JOIN {$db_prefix}objects_entity oe on oe.guid = e.guid"),
  177. 'selects' => array("oe.title", "oe.description"),
  178. 'wheres' => array("oe.title = '$plugin_id'"),
  179. 'limit' => 1,
  180. 'distinct' => false,
  181. );
  182. $plugins = elgg_get_entities($options);
  183. if ($plugins) {
  184. return $plugins[0];
  185. }
  186. return null;
  187. });
  188. }
  189. /**
  190. * Returns if a plugin exists in the system.
  191. *
  192. * @warning This checks only plugins that are registered in the system!
  193. * If the plugin cache is outdated, be sure to regenerate it with
  194. * {@link _elgg_generate_plugin_objects()} first.
  195. *
  196. * @param string $id The plugin ID.
  197. * @return bool
  198. */
  199. function exists($id) {
  200. $plugin = elgg_get_plugin_from_id($id);
  201. return ($plugin) ? true : false;
  202. }
  203. /**
  204. * Returns the highest priority of the plugins
  205. *
  206. * @return int
  207. * @access private
  208. */
  209. function getMaxPriority() {
  210. $db_prefix = get_config('dbprefix');
  211. $priority = _elgg_namespace_plugin_private_setting('internal', 'priority');
  212. $plugin_subtype = get_subtype_id('object', 'plugin');
  213. $q = "SELECT MAX(CAST(ps.value AS unsigned)) as max
  214. FROM {$db_prefix}entities e, {$db_prefix}private_settings ps
  215. WHERE ps.name = '$priority'
  216. AND ps.entity_guid = e.guid
  217. AND e.type = 'object' and e.subtype = $plugin_subtype";
  218. $data = get_data($q);
  219. if ($data) {
  220. $max = $data[0]->max;
  221. } else {
  222. $max = 1;
  223. }
  224. // can't have a priority of 0.
  225. return ($max) ? $max : 1;
  226. }
  227. /**
  228. * Returns if a plugin is active for a current site.
  229. *
  230. * @param string $plugin_id The plugin ID
  231. * @param int $site_guid The site guid
  232. * @return bool
  233. */
  234. function isActive($plugin_id, $site_guid = null) {
  235. $current_site_guid = elgg_get_site_entity()->guid;
  236. if ($this->active_ids_known
  237. && ($site_guid === null || $site_guid == $current_site_guid)) {
  238. return isset($this->active_ids[$plugin_id]);
  239. }
  240. if ($site_guid) {
  241. $site = get_entity($site_guid);
  242. } else {
  243. $site = elgg_get_site_entity();
  244. }
  245. if (!($site instanceof \ElggSite)) {
  246. return false;
  247. }
  248. $plugin = elgg_get_plugin_from_id($plugin_id);
  249. if (!$plugin) {
  250. return false;
  251. }
  252. return $plugin->isActive($site->guid);
  253. }
  254. /**
  255. * Loads all active plugins in the order specified in the tool admin panel.
  256. *
  257. * @note This is called on every page load. If a plugin is active and problematic, it
  258. * will be disabled and a visible error emitted. This does not check the deps system because
  259. * that was too slow.
  260. *
  261. * @return bool
  262. * @access private
  263. */
  264. function load() {
  265. $plugins_path = elgg_get_plugins_path();
  266. $start_flags = ELGG_PLUGIN_INCLUDE_START |
  267. ELGG_PLUGIN_REGISTER_VIEWS |
  268. ELGG_PLUGIN_REGISTER_LANGUAGES |
  269. ELGG_PLUGIN_REGISTER_CLASSES;
  270. if (!$plugins_path) {
  271. return false;
  272. }
  273. // temporary disable all plugins if there is a file called 'disabled' in the plugin dir
  274. if (file_exists("$plugins_path/disabled")) {
  275. if (elgg_is_admin_logged_in() && elgg_in_context('admin')) {
  276. system_message(_elgg_services()->translator->translate('plugins:disabled'));
  277. }
  278. return false;
  279. }
  280. if (elgg_get_config('system_cache_loaded')) {
  281. $start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_VIEWS;
  282. }
  283. if (elgg_get_config('i18n_loaded_from_cache')) {
  284. $start_flags = $start_flags & ~ELGG_PLUGIN_REGISTER_LANGUAGES;
  285. }
  286. $return = true;
  287. $plugins = $this->find('active');
  288. if ($plugins) {
  289. foreach ($plugins as $plugin) {
  290. $id = $plugin->getID();
  291. try {
  292. $plugin->start($start_flags);
  293. $this->active_ids[$id] = true;
  294. } catch (Exception $e) {
  295. $plugin->deactivate();
  296. $msg = _elgg_services()->translator->translate('PluginException:CannotStart',
  297. array($id, $plugin->guid, $e->getMessage()));
  298. elgg_add_admin_notice("cannot_start $id", $msg);
  299. $return = false;
  300. continue;
  301. }
  302. }
  303. }
  304. $this->active_ids_known = true;
  305. return $return;
  306. }
  307. /**
  308. * Returns an ordered list of plugins
  309. *
  310. * @param string $status The status of the plugins. active, inactive, or all.
  311. * @param mixed $site_guid Optional site guid
  312. * @return \ElggPlugin[]
  313. */
  314. function find($status = 'active', $site_guid = null) {
  315. $db_prefix = get_config('dbprefix');
  316. $priority = _elgg_namespace_plugin_private_setting('internal', 'priority');
  317. if (!$site_guid) {
  318. $site = get_config('site');
  319. $site_guid = $site->guid;
  320. }
  321. // grab plugins
  322. $options = array(
  323. 'type' => 'object',
  324. 'subtype' => 'plugin',
  325. 'limit' => ELGG_ENTITIES_NO_VALUE,
  326. 'selects' => array('plugin_oe.*'),
  327. 'joins' => array(
  328. "JOIN {$db_prefix}private_settings ps on ps.entity_guid = e.guid",
  329. "JOIN {$db_prefix}objects_entity plugin_oe on plugin_oe.guid = e.guid"
  330. ),
  331. 'wheres' => array("ps.name = '$priority'"),
  332. 'order_by' => "CAST(ps.value as unsigned), e.guid",
  333. 'distinct' => false,
  334. );
  335. switch ($status) {
  336. case 'active':
  337. $options['relationship'] = 'active_plugin';
  338. $options['relationship_guid'] = $site_guid;
  339. $options['inverse_relationship'] = true;
  340. break;
  341. case 'inactive':
  342. $options['wheres'][] = "NOT EXISTS (
  343. SELECT 1 FROM {$db_prefix}entity_relationships active_er
  344. WHERE active_er.guid_one = e.guid
  345. AND active_er.relationship = 'active_plugin'
  346. AND active_er.guid_two = $site_guid)";
  347. break;
  348. case 'all':
  349. default:
  350. break;
  351. }
  352. $old_ia = elgg_set_ignore_access(true);
  353. $plugins = elgg_get_entities_from_relationship($options);
  354. elgg_set_ignore_access($old_ia);
  355. return $plugins;
  356. }
  357. /**
  358. * Reorder plugins to an order specified by the array.
  359. * Plugins not included in this array will be appended to the end.
  360. *
  361. * @note This doesn't use the \ElggPlugin->setPriority() method because
  362. * all plugins are being changed and we don't want it to automatically
  363. * reorder plugins.
  364. *
  365. * @param array $order An array of plugin ids in the order to set them
  366. * @return bool
  367. * @access private
  368. */
  369. function setPriorities(array $order) {
  370. $name = _elgg_namespace_plugin_private_setting('internal', 'priority');
  371. $plugins = elgg_get_plugins('any');
  372. if (!$plugins) {
  373. return false;
  374. }
  375. $return = true;
  376. // reindex to get standard counting. no need to increment by 10.
  377. // though we do start with 1
  378. $order = array_values($order);
  379. $missing_plugins = array();
  380. /* @var \ElggPlugin[] $missing_plugins */
  381. foreach ($plugins as $plugin) {
  382. $plugin_id = $plugin->getID();
  383. if (!in_array($plugin_id, $order)) {
  384. $missing_plugins[] = $plugin;
  385. continue;
  386. }
  387. $priority = array_search($plugin_id, $order) + 1;
  388. if (!$plugin->setPrivateSetting($name, $priority)) {
  389. $return = false;
  390. break;
  391. }
  392. }
  393. // set the missing plugins' priorities
  394. if ($return && $missing_plugins) {
  395. if (!isset($priority)) {
  396. $priority = 0;
  397. }
  398. foreach ($missing_plugins as $plugin) {
  399. $priority++;
  400. if (!$plugin->setPrivateSetting($name, $priority)) {
  401. $return = false;
  402. break;
  403. }
  404. }
  405. }
  406. return $return;
  407. }
  408. /**
  409. * Reindexes all plugin priorities starting at 1.
  410. *
  411. * @todo Can this be done in a single sql command?
  412. * @return bool
  413. * @access private
  414. */
  415. function reindexPriorities() {
  416. return _elgg_set_plugin_priorities(array());
  417. }
  418. /**
  419. * Namespaces a string to be used as a private setting name for a plugin.
  420. *
  421. * For user_settings, two namespaces are added: a user setting namespace and the
  422. * plugin id.
  423. *
  424. * For internal (plugin priority), there is a single internal namespace added.
  425. *
  426. * @param string $type The type of setting: user_setting or internal.
  427. * @param string $name The name to namespace.
  428. * @param string $id The plugin's ID to namespace with. Required for user_setting.
  429. * @return string
  430. * @access private
  431. */
  432. function namespacePrivateSetting($type, $name, $id = null) {
  433. switch ($type) {
  434. // commented out because it breaks $plugin->$name access to variables
  435. //case 'setting':
  436. // $name = ELGG_PLUGIN_SETTING_PREFIX . $name;
  437. // break;
  438. case 'user_setting':
  439. if (!$id) {
  440. elgg_deprecated_notice("You must pass the plugin id to _elgg_namespace_plugin_private_setting() for user settings", 1.9);
  441. $id = elgg_get_calling_plugin_id();
  442. }
  443. $name = ELGG_PLUGIN_USER_SETTING_PREFIX . "$id:$name";
  444. break;
  445. case 'internal':
  446. $name = ELGG_PLUGIN_INTERNAL_PREFIX . $name;
  447. break;
  448. }
  449. return $name;
  450. }
  451. /**
  452. * Returns an array of all provides from all active plugins.
  453. *
  454. * Array in the form array(
  455. * 'provide_type' => array(
  456. * 'provided_name' => array(
  457. * 'version' => '1.8',
  458. * 'provided_by' => 'provider_plugin_id'
  459. * )
  460. * )
  461. * )
  462. *
  463. * @param string $type The type of provides to return
  464. * @param string $name A specific provided name to return. Requires $provide_type.
  465. *
  466. * @return array
  467. * @access private
  468. */
  469. function getProvides($type = null, $name = null) {
  470. global $ELGG_PLUGINS_PROVIDES_CACHE;
  471. if (!isset($ELGG_PLUGINS_PROVIDES_CACHE)) {
  472. $active_plugins = elgg_get_plugins('active');
  473. $provides = array();
  474. foreach ($active_plugins as $plugin) {
  475. $plugin_provides = array();
  476. $manifest = $plugin->getManifest();
  477. if ($manifest instanceof \ElggPluginManifest) {
  478. $plugin_provides = $plugin->getManifest()->getProvides();
  479. }
  480. if ($plugin_provides) {
  481. foreach ($plugin_provides as $provided) {
  482. $provides[$provided['type']][$provided['name']] = array(
  483. 'version' => $provided['version'],
  484. 'provided_by' => $plugin->getID()
  485. );
  486. }
  487. }
  488. }
  489. $ELGG_PLUGINS_PROVIDES_CACHE = $provides;
  490. }
  491. if ($type && $name) {
  492. if (isset($ELGG_PLUGINS_PROVIDES_CACHE[$type][$name])) {
  493. return $ELGG_PLUGINS_PROVIDES_CACHE[$type][$name];
  494. } else {
  495. return false;
  496. }
  497. } elseif ($type) {
  498. if (isset($ELGG_PLUGINS_PROVIDES_CACHE[$type])) {
  499. return $ELGG_PLUGINS_PROVIDES_CACHE[$type];
  500. } else {
  501. return false;
  502. }
  503. }
  504. return $ELGG_PLUGINS_PROVIDES_CACHE;
  505. }
  506. /**
  507. * Deletes all cached data on plugins being provided.
  508. *
  509. * @return boolean
  510. * @access private
  511. */
  512. function invalidateProvidesCache() {
  513. global $ELGG_PLUGINS_PROVIDES_CACHE;
  514. $ELGG_PLUGINS_PROVIDES_CACHE = null;
  515. return true;
  516. }
  517. /**
  518. * Delete the cache holding whether plugins are active or not
  519. *
  520. * @return void
  521. * @access private
  522. */
  523. public function invalidateIsActiveCache() {
  524. $this->active_ids = array();
  525. $this->active_ids_known = false;
  526. }
  527. /**
  528. * Checks if a plugin is currently providing $type and $name, and optionally
  529. * checking a version.
  530. *
  531. * @param string $type The type of the provide
  532. * @param string $name The name of the provide
  533. * @param string $version A version to check against
  534. * @param string $comparison The comparison operator to use in version_compare()
  535. *
  536. * @return array An array in the form array(
  537. * 'status' => bool Does the provide exist?,
  538. * 'value' => string The version provided
  539. * )
  540. * @access private
  541. */
  542. function checkProvides($type, $name, $version = null, $comparison = 'ge') {
  543. $provided = _elgg_get_plugins_provides($type, $name);
  544. if (!$provided) {
  545. return array(
  546. 'status' => false,
  547. 'value' => ''
  548. );
  549. }
  550. if ($version) {
  551. $status = version_compare($provided['version'], $version, $comparison);
  552. } else {
  553. $status = true;
  554. }
  555. return array(
  556. 'status' => $status,
  557. 'value' => $provided['version']
  558. );
  559. }
  560. /**
  561. * Returns an array of parsed strings for a dependency in the
  562. * format: array(
  563. * 'type' => requires, conflicts, or provides.
  564. * 'name' => The name of the requirement / conflict
  565. * 'value' => A string representing the expected value: <1, >=3, !=enabled
  566. * 'local_value' => The current value, ("Not installed")
  567. * 'comment' => Free form text to help resovle the problem ("Enable / Search for plugin <link>")
  568. * )
  569. *
  570. * @param array $dep An \ElggPluginPackage dependency array
  571. * @return array
  572. * @access private
  573. */
  574. function getDependencyStrings($dep) {
  575. $translator = _elgg_services()->translator;
  576. $dep_system = elgg_extract('type', $dep);
  577. $info = elgg_extract('dep', $dep);
  578. $type = elgg_extract('type', $info);
  579. if (!$dep_system || !$info || !$type) {
  580. return false;
  581. }
  582. // rewrite some of these to be more readable
  583. $comparison = elgg_extract('comparison', $info);
  584. switch($comparison) {
  585. case 'lt':
  586. $comparison = '<';
  587. break;
  588. case 'gt':
  589. $comparison = '>';
  590. break;
  591. case 'ge':
  592. $comparison = '>=';
  593. break;
  594. case 'le':
  595. $comparison = '<=';
  596. break;
  597. default:
  598. //keep $comparison value intact
  599. break;
  600. }
  601. /*
  602. 'requires' 'plugin oauth_lib' <1.3 1.3 'downgrade'
  603. 'requires' 'php setting bob' >3 3 'change it'
  604. 'conflicts' 'php setting' >3 4 'change it'
  605. 'conflicted''plugin profile' any 1.8 'disable profile'
  606. 'provides' 'plugin oauth_lib' 1.3 -- --
  607. 'priority' 'before blog' -- after 'move it'
  608. */
  609. $strings = array();
  610. $strings['type'] = $translator->translate('ElggPlugin:Dependencies:' . ucwords($dep_system));
  611. switch ($type) {
  612. case 'elgg_version':
  613. case 'elgg_release':
  614. // 'Elgg Version'
  615. $strings['name'] = $translator->translate('ElggPlugin:Dependencies:Elgg');
  616. $strings['expected_value'] = "$comparison {$info['version']}";
  617. $strings['local_value'] = $dep['value'];
  618. $strings['comment'] = '';
  619. break;
  620. case 'php_version':
  621. // 'PHP version'
  622. $strings['name'] = $translator->translate('ElggPlugin:Dependencies:PhpVersion');
  623. $strings['expected_value'] = "$comparison {$info['version']}";
  624. $strings['local_value'] = $dep['value'];
  625. $strings['comment'] = '';
  626. break;
  627. case 'php_extension':
  628. // PHP Extension %s [version]
  629. $strings['name'] = $translator->translate('ElggPlugin:Dependencies:PhpExtension', array($info['name']));
  630. if ($info['version']) {
  631. $strings['expected_value'] = "$comparison {$info['version']}";
  632. $strings['local_value'] = $dep['value'];
  633. } else {
  634. $strings['expected_value'] = '';
  635. $strings['local_value'] = '';
  636. }
  637. $strings['comment'] = '';
  638. break;
  639. case 'php_ini':
  640. $strings['name'] = $translator->translate('ElggPlugin:Dependencies:PhpIni', array($info['name']));
  641. $strings['expected_value'] = "$comparison {$info['value']}";
  642. $strings['local_value'] = $dep['value'];
  643. $strings['comment'] = '';
  644. break;
  645. case 'plugin':
  646. $strings['name'] = $translator->translate('ElggPlugin:Dependencies:Plugin', array($info['name']));
  647. $expected = $info['version'] ? "$comparison {$info['version']}" : $translator->translate('any');
  648. $strings['expected_value'] = $expected;
  649. $strings['local_value'] = $dep['value'] ? $dep['value'] : '--';
  650. $strings['comment'] = '';
  651. break;
  652. case 'priority':
  653. $expected_priority = ucwords($info['priority']);
  654. $real_priority = ucwords($dep['value']);
  655. $strings['name'] = $translator->translate('ElggPlugin:Dependencies:Priority');
  656. $strings['expected_value'] = $translator->translate("ElggPlugin:Dependencies:Priority:$expected_priority", array($info['plugin']));
  657. $strings['local_value'] = $translator->translate("ElggPlugin:Dependencies:Priority:$real_priority", array($info['plugin']));
  658. $strings['comment'] = '';
  659. break;
  660. }
  661. if ($dep['type'] == 'suggests') {
  662. if ($dep['status']) {
  663. $strings['comment'] = $translator->translate('ok');
  664. } else {
  665. $strings['comment'] = $translator->translate('ElggPlugin:Dependencies:Suggests:Unsatisfied');
  666. }
  667. } else {
  668. if ($dep['status']) {
  669. $strings['comment'] = $translator->translate('ok');
  670. } else {
  671. $strings['comment'] = $translator->translate('error');
  672. }
  673. }
  674. return $strings;
  675. }
  676. /**
  677. * Returns an array of all plugin user settings for a user.
  678. *
  679. * @param int $user_guid The user GUID or 0 for the currently logged in user.
  680. * @param string $plugin_id The plugin ID (Required)
  681. * @param bool $return_obj Return settings as an object? This can be used to in reusable
  682. * views where the settings are passed as $vars['entity'].
  683. * @return array
  684. * @see \ElggPlugin::getAllUserSettings()
  685. */
  686. function getAllUserSettings($user_guid = 0, $plugin_id = null, $return_obj = false) {
  687. if ($plugin_id) {
  688. $plugin = elgg_get_plugin_from_id($plugin_id);
  689. } else {
  690. elgg_deprecated_notice('elgg_get_all_plugin_user_settings() requires plugin_id to be set', 1.9);
  691. $plugin = elgg_get_calling_plugin_entity();
  692. }
  693. if (!$plugin instanceof \ElggPlugin) {
  694. return false;
  695. }
  696. $settings = $plugin->getAllUserSettings((int)$user_guid);
  697. if ($settings && $return_obj) {
  698. $return = new \stdClass;
  699. foreach ($settings as $k => $v) {
  700. $return->$k = $v;
  701. }
  702. return $return;
  703. } else {
  704. return $settings;
  705. }
  706. }
  707. /**
  708. * Set a user specific setting for a plugin.
  709. *
  710. * @param string $name The name. Note: cannot be "title".
  711. * @param mixed $value The value.
  712. * @param int $user_guid The user GUID or 0 for the currently logged in user.
  713. * @param string $plugin_id The plugin ID (Required)
  714. *
  715. * @return bool
  716. * @see \ElggPlugin::setUserSetting()
  717. */
  718. function setUserSetting($name, $value, $user_guid = 0, $plugin_id = null) {
  719. if ($plugin_id) {
  720. $plugin = elgg_get_plugin_from_id($plugin_id);
  721. } else {
  722. elgg_deprecated_notice('elgg_set_plugin_user_setting() requires plugin_id to be set', 1.9);
  723. $plugin = elgg_get_calling_plugin_entity();
  724. }
  725. if (!$plugin) {
  726. return false;
  727. }
  728. return $plugin->setUserSetting($name, $value, (int)$user_guid);
  729. }
  730. /**
  731. * Unsets a user-specific plugin setting
  732. *
  733. * @param string $name Name of the setting
  734. * @param int $user_guid The user GUID or 0 for the currently logged in user.
  735. * @param string $plugin_id The plugin ID (Required)
  736. *
  737. * @return bool
  738. * @see \ElggPlugin::unsetUserSetting()
  739. */
  740. function unsetUserSetting($name, $user_guid = 0, $plugin_id = null) {
  741. if ($plugin_id) {
  742. $plugin = elgg_get_plugin_from_id($plugin_id);
  743. } else {
  744. elgg_deprecated_notice('elgg_unset_plugin_user_setting() requires plugin_id to be set', 1.9);
  745. $plugin = elgg_get_calling_plugin_entity();
  746. }
  747. if (!$plugin) {
  748. return false;
  749. }
  750. return $plugin->unsetUserSetting($name, (int)$user_guid);
  751. }
  752. /**
  753. * Get a user specific setting for a plugin.
  754. *
  755. * @param string $name The name of the setting.
  756. * @param int $user_guid The user GUID or 0 for the currently logged in user.
  757. * @param string $plugin_id The plugin ID (Required)
  758. * @param mixed $default The default value to return if none is set
  759. *
  760. * @return mixed
  761. * @see \ElggPlugin::getUserSetting()
  762. */
  763. function getUserSetting($name, $user_guid = 0, $plugin_id = null, $default = null) {
  764. if ($plugin_id) {
  765. $plugin = elgg_get_plugin_from_id($plugin_id);
  766. } else {
  767. elgg_deprecated_notice('elgg_get_plugin_user_setting() requires plugin_id to be set', 1.9);
  768. $plugin = elgg_get_calling_plugin_entity();
  769. }
  770. if (!$plugin) {
  771. return false;
  772. }
  773. return $plugin->getUserSetting($name, (int)$user_guid, $default);
  774. }
  775. /**
  776. * Set a setting for a plugin.
  777. *
  778. * @param string $name The name of the setting - note, can't be "title".
  779. * @param mixed $value The value.
  780. * @param string $plugin_id The plugin ID (Required)
  781. *
  782. * @return bool
  783. * @see \ElggPlugin::setSetting()
  784. */
  785. function setSetting($name, $value, $plugin_id = null) {
  786. if ($plugin_id) {
  787. $plugin = elgg_get_plugin_from_id($plugin_id);
  788. } else {
  789. elgg_deprecated_notice('elgg_set_plugin_setting() requires plugin_id to be set', 1.9);
  790. $plugin = elgg_get_calling_plugin_entity();
  791. }
  792. if (!$plugin) {
  793. return false;
  794. }
  795. return $plugin->setSetting($name, $value);
  796. }
  797. /**
  798. * Get setting for a plugin.
  799. *
  800. * @param string $name The name of the setting.
  801. * @param string $plugin_id The plugin ID (Required)
  802. * @param mixed $default The default value to return if none is set
  803. *
  804. * @return mixed
  805. * @see \ElggPlugin::getSetting()
  806. */
  807. function getSetting($name, $plugin_id = null, $default = null) {
  808. if ($plugin_id) {
  809. $plugin = elgg_get_plugin_from_id($plugin_id);
  810. } else {
  811. elgg_deprecated_notice('elgg_get_plugin_setting() requires plugin_id to be set', 1.9);
  812. $plugin = elgg_get_calling_plugin_entity();
  813. }
  814. if (!$plugin) {
  815. return false;
  816. }
  817. return $plugin->getSetting($name, $default);
  818. }
  819. /**
  820. * Unsets a plugin setting.
  821. *
  822. * @param string $name The name of the setting.
  823. * @param string $plugin_id The plugin ID (Required)
  824. *
  825. * @return bool
  826. * @see \ElggPlugin::unsetSetting()
  827. */
  828. function unsetSetting($name, $plugin_id = null) {
  829. if ($plugin_id) {
  830. $plugin = elgg_get_plugin_from_id($plugin_id);
  831. } else {
  832. elgg_deprecated_notice('elgg_unset_plugin_setting() requires plugin_id to be set', 1.9);
  833. $plugin = elgg_get_calling_plugin_entity();
  834. }
  835. if (!$plugin) {
  836. return false;
  837. }
  838. return $plugin->unsetSetting($name);
  839. }
  840. /**
  841. * Unsets all plugin settings for a plugin.
  842. *
  843. * @param string $plugin_id The plugin ID (Required)
  844. *
  845. * @return bool
  846. * @see \ElggPlugin::unsetAllSettings()
  847. */
  848. function unsetAllSettings($plugin_id = null) {
  849. if ($plugin_id) {
  850. $plugin = elgg_get_plugin_from_id($plugin_id);
  851. } else {
  852. elgg_deprecated_notice('elgg_unset_all_plugin_settings() requires plugin_id to be set', 1.9);
  853. $plugin = elgg_get_calling_plugin_entity();
  854. }
  855. if (!$plugin) {
  856. return false;
  857. }
  858. return $plugin->unsetAllSettings();
  859. }
  860. /**
  861. * Returns entities based upon plugin user settings.
  862. * Takes all the options for {@link elgg_get_entities_from_private_settings()}
  863. * in addition to the ones below.
  864. *
  865. * @param array $options Array in the format:
  866. *
  867. * plugin_id => STR The plugin id. Required.
  868. *
  869. * plugin_user_setting_names => null|ARR private setting names
  870. *
  871. * plugin_user_setting_values => null|ARR metadata values
  872. *
  873. * plugin_user_setting_name_value_pairs => null|ARR (
  874. * name => 'name',
  875. * value => 'value',
  876. * 'operand' => '=',
  877. * )
  878. * Currently if multiple values are sent via
  879. * an array (value => array('value1', 'value2')
  880. * the pair's operand will be forced to "IN".
  881. *
  882. * plugin_user_setting_name_value_pairs_operator => null|STR The operator to use for combining
  883. * (name = value) OPERATOR (name = value); default AND
  884. *
  885. * @return mixed int If count, int. If not count, array. false on errors.
  886. */
  887. function getEntitiesFromUserSettings(array $options = array()) {
  888. if (!isset($options['plugin_id'])) {
  889. elgg_deprecated_notice("'plugin_id' is now required for elgg_get_entities_from_plugin_user_settings()", 1.9);
  890. $options['plugin_id'] = elgg_get_calling_plugin_id();
  891. }
  892. $singulars = array('plugin_user_setting_name', 'plugin_user_setting_value',
  893. 'plugin_user_setting_name_value_pair');
  894. $options = _elgg_normalize_plural_options_array($options, $singulars);
  895. // rewrite plugin_user_setting_name_* to the right PS ones.
  896. $map = array(
  897. 'plugin_user_setting_names' => 'private_setting_names',
  898. 'plugin_user_setting_values' => 'private_setting_values',
  899. 'plugin_user_setting_name_value_pairs' => 'private_setting_name_value_pairs',
  900. 'plugin_user_setting_name_value_pairs_operator' => 'private_setting_name_value_pairs_operator',
  901. );
  902. foreach ($map as $plugin => $private) {
  903. if (!isset($options[$plugin])) {
  904. continue;
  905. }
  906. if (isset($options[$private])) {
  907. if (!is_array($options[$private])) {
  908. $options[$private] = array($options[$private]);
  909. }
  910. $options[$private] = array_merge($options[$private], $options[$plugin]);
  911. } else {
  912. $options[$private] = $options[$plugin];
  913. }
  914. }
  915. $prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $options['plugin_id']);
  916. $options['private_setting_name_prefix'] = $prefix;
  917. return elgg_get_entities_from_private_settings($options);
  918. }
  919. }