ElggPlugin.php 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  1. <?php
  2. /**
  3. * Stores site-side plugin settings as private data.
  4. *
  5. * This class is currently a stub, allowing a plugin to
  6. * save settings in an object's private settings for each site.
  7. *
  8. * @package Elgg.Core
  9. * @subpackage Plugins.Settings
  10. */
  11. class ElggPlugin extends \ElggObject {
  12. private $package;
  13. private $manifest;
  14. private $path;
  15. private $errorMsg = '';
  16. /**
  17. * Set subtype to 'plugin'
  18. *
  19. * @return void
  20. */
  21. protected function initializeAttributes() {
  22. parent::initializeAttributes();
  23. $this->attributes['subtype'] = "plugin";
  24. // plugins must be public.
  25. $this->access_id = ACCESS_PUBLIC;
  26. }
  27. /**
  28. * Creates a new plugin from path
  29. *
  30. * @note Internal: also supports database objects
  31. *
  32. * @warning Unlike other \ElggEntity objects, you cannot null instantiate
  33. * \ElggPlugin. You must provide the path to the plugin directory.
  34. *
  35. * @param string $path The absolute path of the plugin
  36. *
  37. * @throws PluginException
  38. */
  39. public function __construct($path) {
  40. if (!$path) {
  41. throw new \PluginException("ElggPlugin cannot be null instantiated. You must pass a full path.");
  42. }
  43. if (is_object($path)) {
  44. // database object
  45. parent::__construct($path);
  46. $this->path = _elgg_services()->config->getPluginsPath() . $this->getID();
  47. } else if (is_numeric($path)) {
  48. // guid
  49. // @todo plugins with directory names of '12345'
  50. elgg_deprecated_notice("Use elgg_get_plugin_from_id() to load a plugin.", 1.9);
  51. parent::__construct($path);
  52. $this->path = _elgg_services()->config->getPluginsPath() . $this->getID();
  53. } else {
  54. $this->initializeAttributes();
  55. $mod_dir = _elgg_services()->config->getPluginsPath();
  56. // not a full path, so assume a directory name and use the default path
  57. if (strpos($path, $mod_dir) !== 0) {
  58. elgg_deprecated_notice("You should pass a full path to ElggPlugin.", 1.9);
  59. $path = $mod_dir . $path;
  60. }
  61. // path checking is done in the package
  62. $path = sanitise_filepath($path);
  63. $this->path = $path;
  64. $path_parts = explode('/', rtrim($path, '/'));
  65. $plugin_id = array_pop($path_parts);
  66. $this->title = $plugin_id;
  67. // check if we're loading an existing plugin
  68. $existing_plugin = elgg_get_plugin_from_id($plugin_id);
  69. if ($existing_plugin) {
  70. $this->load($existing_plugin->guid);
  71. }
  72. }
  73. _elgg_cache_plugin_by_id($this);
  74. }
  75. /**
  76. * Save the plugin object. Make sure required values exist.
  77. *
  78. * @see \ElggObject::save()
  79. * @return bool
  80. */
  81. public function save() {
  82. // own by the current site so users can be deleted without affecting plugins
  83. $site = _elgg_services()->configTable->get('site');
  84. $this->attributes['site_guid'] = $site->guid;
  85. $this->attributes['owner_guid'] = $site->guid;
  86. $this->attributes['container_guid'] = $site->guid;
  87. if (parent::save()) {
  88. // make sure we have a priority
  89. $priority = $this->getPriority();
  90. if ($priority === false || $priority === null) {
  91. return $this->setPriority('last');
  92. }
  93. } else {
  94. return false;
  95. }
  96. }
  97. // Plugin ID and path
  98. /**
  99. * Returns the ID (dir name) of this plugin
  100. *
  101. * @return string
  102. */
  103. public function getID() {
  104. return $this->title;
  105. }
  106. /**
  107. * Returns the manifest's name if available, otherwise the ID.
  108. *
  109. * @return string
  110. * @since 1.8.1
  111. */
  112. public function getFriendlyName() {
  113. $manifest = $this->getManifest();
  114. if ($manifest) {
  115. return $manifest->getName();
  116. }
  117. return $this->getID();
  118. }
  119. /**
  120. * Returns the plugin's full path with trailing slash.
  121. *
  122. * @return string
  123. */
  124. public function getPath() {
  125. return sanitise_filepath($this->path);
  126. }
  127. /**
  128. * Sets the location of this plugin.
  129. *
  130. * @param string $id The path to the plugin's dir.
  131. * @return bool
  132. */
  133. public function setID($id) {
  134. return $this->attributes['title'] = $id;
  135. }
  136. /**
  137. * Returns an array of available markdown files for this plugin
  138. *
  139. * @return array
  140. */
  141. public function getAvailableTextFiles() {
  142. $filenames = $this->getPackage()->getTextFilenames();
  143. $files = array();
  144. foreach ($filenames as $filename) {
  145. if ($this->canReadFile($filename)) {
  146. $files[$filename] = "$this->path/$filename";
  147. }
  148. }
  149. return $files;
  150. }
  151. // Load Priority
  152. /**
  153. * Gets the plugin's load priority.
  154. *
  155. * @return int
  156. */
  157. public function getPriority() {
  158. $name = _elgg_namespace_plugin_private_setting('internal', 'priority');
  159. return $this->$name;
  160. }
  161. /**
  162. * Sets the priority of the plugin
  163. *
  164. * @param mixed $priority The priority to set. One of +1, -1, first, last, or a number.
  165. * If given a number, this will displace all plugins at that number
  166. * and set their priorities +1
  167. * @param mixed $site_guid Optional site GUID.
  168. * @return bool
  169. */
  170. public function setPriority($priority, $site_guid = null) {
  171. if (!$this->guid) {
  172. return false;
  173. }
  174. $db_prefix = _elgg_services()->configTable->get('dbprefix');
  175. $name = _elgg_namespace_plugin_private_setting('internal', 'priority');
  176. // if no priority assume a priority of 1
  177. $old_priority = (int) $this->getPriority();
  178. $old_priority = (!$old_priority) ? 1 : $old_priority;
  179. $max_priority = _elgg_get_max_plugin_priority();
  180. // can't use switch here because it's not strict and
  181. // php evaluates +1 == 1
  182. if ($priority === '+1') {
  183. $priority = $old_priority + 1;
  184. } elseif ($priority === '-1') {
  185. $priority = $old_priority - 1;
  186. } elseif ($priority === 'first') {
  187. $priority = 1;
  188. } elseif ($priority === 'last') {
  189. $priority = $max_priority;
  190. }
  191. // should be a number by now
  192. if ($priority > 0) {
  193. if (!is_numeric($priority)) {
  194. return false;
  195. }
  196. // there's nothing above the max.
  197. if ($priority > $max_priority) {
  198. $priority = $max_priority;
  199. }
  200. // there's nothing below 1.
  201. if ($priority < 1) {
  202. $priority = 1;
  203. }
  204. if ($priority > $old_priority) {
  205. $op = '-';
  206. $where = "CAST(value as unsigned) BETWEEN $old_priority AND $priority";
  207. } else {
  208. $op = '+';
  209. $where = "CAST(value as unsigned) BETWEEN $priority AND $old_priority";
  210. }
  211. // displace the ones affected by this change
  212. $q = "UPDATE {$db_prefix}private_settings
  213. SET value = CAST(value as unsigned) $op 1
  214. WHERE entity_guid != $this->guid
  215. AND name = '$name'
  216. AND $where";
  217. if (!$this->getDatabase()->updateData($q)) {
  218. return false;
  219. }
  220. // set this priority
  221. if ($this->setPrivateSetting($name, $priority)) {
  222. return true;
  223. } else {
  224. return false;
  225. }
  226. }
  227. return false;
  228. }
  229. // Plugin settings
  230. /**
  231. * Returns a plugin setting
  232. *
  233. * @param string $name The setting name
  234. * @param mixed $default The default value to return if none is set
  235. * @return mixed
  236. */
  237. public function getSetting($name, $default = null) {
  238. $val = $this->$name;
  239. return $val !== null ? $val : $default;
  240. }
  241. /**
  242. * Returns an array of all settings saved for this plugin.
  243. *
  244. * @note Unlike user settings, plugin settings are not namespaced.
  245. *
  246. * @return array An array of key/value pairs.
  247. */
  248. public function getAllSettings() {
  249. if (!$this->guid) {
  250. return false;
  251. }
  252. $db_prefix = _elgg_services()->config->get('dbprefix');
  253. // need to remove all namespaced private settings.
  254. $us_prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
  255. $is_prefix = _elgg_namespace_plugin_private_setting('internal', '', $this->getID());
  256. // Get private settings for user
  257. $q = "SELECT * FROM {$db_prefix}private_settings
  258. WHERE entity_guid = $this->guid
  259. AND name NOT LIKE '$us_prefix%'
  260. AND name NOT LIKE '$is_prefix%'";
  261. $private_settings = $this->getDatabase()->getData($q);
  262. $return = array();
  263. if ($private_settings) {
  264. foreach ($private_settings as $setting) {
  265. $return[$setting->name] = $setting->value;
  266. }
  267. }
  268. return $return;
  269. }
  270. /**
  271. * Set a plugin setting for the plugin
  272. *
  273. * @todo This will only work once the plugin has a GUID.
  274. *
  275. * @param string $name The name to set
  276. * @param string $value The value to set
  277. *
  278. * @return bool
  279. */
  280. public function setSetting($name, $value) {
  281. if (!$this->guid) {
  282. return false;
  283. }
  284. // Hook to validate setting
  285. $value = elgg_trigger_plugin_hook('setting', 'plugin', array(
  286. 'plugin_id' => $this->getID(),
  287. 'plugin' => $this,
  288. 'name' => $name,
  289. 'value' => $value,
  290. ), $value);
  291. return $this->setPrivateSetting($name, $value);
  292. }
  293. /**
  294. * Removes a plugin setting name and value.
  295. *
  296. * @param string $name The setting name to remove
  297. *
  298. * @return bool
  299. */
  300. public function unsetSetting($name) {
  301. return remove_private_setting($this->guid, $name);
  302. }
  303. /**
  304. * Removes all settings for this plugin.
  305. *
  306. * @todo Should be a better way to do this without dropping to raw SQL.
  307. * @todo If we could namespace the plugin settings this would be cleaner.
  308. * @todo this shouldn't work because ps_prefix will be empty string
  309. * @return bool
  310. */
  311. public function unsetAllSettings() {
  312. $db_prefix = _elgg_services()->configTable->get('dbprefix');
  313. $us_prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
  314. $is_prefix = _elgg_namespace_plugin_private_setting('internal', '', $this->getID());
  315. $q = "DELETE FROM {$db_prefix}private_settings
  316. WHERE entity_guid = $this->guid
  317. AND name NOT LIKE '$us_prefix%'
  318. AND name NOT LIKE '$is_prefix%'";
  319. return $this->getDatabase()->deleteData($q);
  320. }
  321. // User settings
  322. /**
  323. * Returns a user's setting for this plugin
  324. *
  325. * @param string $name The setting name
  326. * @param int $user_guid The user GUID
  327. * @param mixed $default The default value to return if none is set
  328. *
  329. * @return mixed The setting string value, the default value or false if there is no user
  330. */
  331. public function getUserSetting($name, $user_guid = 0, $default = null) {
  332. $user_guid = (int)$user_guid;
  333. if ($user_guid) {
  334. $user = get_entity($user_guid);
  335. } else {
  336. $user = _elgg_services()->session->getLoggedInUser();
  337. }
  338. if (!($user instanceof \ElggUser)) {
  339. return false;
  340. }
  341. $name = _elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
  342. $val = get_private_setting($user->guid, $name);
  343. return $val !== null ? $val : $default;
  344. }
  345. /**
  346. * Returns an array of all user settings saved for this plugin for the user.
  347. *
  348. * @note Plugin settings are saved with a prefix. This removes that prefix.
  349. *
  350. * @param int $user_guid The user GUID. Defaults to logged in.
  351. * @return array An array of key/value pairs.
  352. */
  353. public function getAllUserSettings($user_guid = 0) {
  354. $user_guid = (int)$user_guid;
  355. if ($user_guid) {
  356. $user = get_entity($user_guid);
  357. } else {
  358. $user = _elgg_services()->session->getLoggedInUser();
  359. }
  360. if (!($user instanceof \ElggUser)) {
  361. return false;
  362. }
  363. $db_prefix = _elgg_services()->config->get('dbprefix');
  364. // send an empty name so we just get the first part of the namespace
  365. $ps_prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
  366. $ps_prefix_len = strlen($ps_prefix);
  367. // Get private settings for user
  368. $q = "SELECT * FROM {$db_prefix}private_settings
  369. WHERE entity_guid = {$user->guid}
  370. AND name LIKE '$ps_prefix%'";
  371. $private_settings = $this->getDatabase()->getData($q);
  372. $return = array();
  373. if ($private_settings) {
  374. foreach ($private_settings as $setting) {
  375. $name = substr($setting->name, $ps_prefix_len);
  376. $value = $setting->value;
  377. $return[$name] = $value;
  378. }
  379. }
  380. return $return;
  381. }
  382. /**
  383. * Sets a user setting for a plugin
  384. *
  385. * @param string $name The setting name
  386. * @param string $value The setting value
  387. * @param int $user_guid The user GUID
  388. *
  389. * @return mixed The new setting ID or false
  390. */
  391. public function setUserSetting($name, $value, $user_guid = 0) {
  392. $user_guid = (int)$user_guid;
  393. if ($user_guid) {
  394. $user = get_entity($user_guid);
  395. } else {
  396. $user = _elgg_services()->session->getLoggedInUser();
  397. }
  398. if (!($user instanceof \ElggUser)) {
  399. return false;
  400. }
  401. // Hook to validate setting
  402. // note: this doesn't pass the namespaced name
  403. $value = _elgg_services()->hooks->trigger('usersetting', 'plugin', array(
  404. 'user' => $user,
  405. 'plugin' => $this,
  406. 'plugin_id' => $this->getID(),
  407. 'name' => $name,
  408. 'value' => $value
  409. ), $value);
  410. // set the namespaced name.
  411. $name = _elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
  412. return set_private_setting($user->guid, $name, $value);
  413. }
  414. /**
  415. * Removes a user setting name and value.
  416. *
  417. * @param string $name The user setting name
  418. * @param int $user_guid The user GUID
  419. * @return bool
  420. */
  421. public function unsetUserSetting($name, $user_guid = 0) {
  422. $user_guid = (int)$user_guid;
  423. if ($user_guid) {
  424. $user = get_entity($user_guid);
  425. } else {
  426. $user = _elgg_services()->session->getLoggedInUser();
  427. }
  428. if (!($user instanceof \ElggUser)) {
  429. return false;
  430. }
  431. // set the namespaced name.
  432. $name = _elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
  433. return remove_private_setting($user->guid, $name);
  434. }
  435. /**
  436. * Removes all User Settings for this plugin for a particular user
  437. *
  438. * Use {@link removeAllUsersSettings()} to remove all user
  439. * settings for all users. (Note the plural 'Users'.)
  440. *
  441. * @warning 0 does not equal logged in user for this method!
  442. * @todo fix that
  443. *
  444. * @param int $user_guid The user GUID to remove user settings.
  445. * @return bool
  446. */
  447. public function unsetAllUserSettings($user_guid) {
  448. $db_prefix = _elgg_services()->configTable->get('dbprefix');
  449. $ps_prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
  450. $q = "DELETE FROM {$db_prefix}private_settings
  451. WHERE entity_guid = $user_guid
  452. AND name LIKE '$ps_prefix%'";
  453. return $this->getDatabase()->deleteData($q);
  454. }
  455. /**
  456. * Removes this plugin's user settings for all users.
  457. *
  458. * Use {@link removeAllUserSettings()} if you just want to remove
  459. * settings for a single user.
  460. *
  461. * @return bool
  462. */
  463. public function unsetAllUsersSettings() {
  464. $db_prefix = _elgg_services()->configTable->get('dbprefix');
  465. $ps_prefix = _elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
  466. $q = "DELETE FROM {$db_prefix}private_settings
  467. WHERE name LIKE '$ps_prefix%'";
  468. return $this->getDatabase()->deleteData($q);
  469. }
  470. // validation
  471. /**
  472. * Returns if the plugin is complete, meaning has all required files
  473. * and Elgg can read them and they make sense.
  474. *
  475. * @todo bad name? This could be confused with isValid() from \ElggPluginPackage.
  476. *
  477. * @return bool
  478. */
  479. public function isValid() {
  480. if (!$this->getID()) {
  481. $this->errorMsg = _elgg_services()->translator->translate('ElggPlugin:MissingID', array($this->guid));
  482. return false;
  483. }
  484. if (!$this->getPackage() instanceof \ElggPluginPackage) {
  485. $this->errorMsg = _elgg_services()->translator->translate('ElggPlugin:NoPluginPackagePackage', array($this->getID(), $this->guid));
  486. return false;
  487. }
  488. if (!$this->getPackage()->isValid()) {
  489. $this->errorMsg = $this->getPackage()->getError();
  490. return false;
  491. }
  492. return true;
  493. }
  494. /**
  495. * Is this plugin active?
  496. *
  497. * @param int $site_guid Optional site guid.
  498. * @return bool
  499. */
  500. public function isActive($site_guid = null) {
  501. if (!$this->guid) {
  502. return false;
  503. }
  504. if ($site_guid) {
  505. $site = get_entity($site_guid);
  506. } else {
  507. $site = _elgg_services()->configTable->get('site');
  508. }
  509. if (!($site instanceof \ElggSite)) {
  510. return false;
  511. }
  512. return check_entity_relationship($this->guid, 'active_plugin', $site->guid);
  513. }
  514. /**
  515. * Checks if this plugin can be activated on the current
  516. * Elgg installation.
  517. *
  518. * @todo remove $site_guid param or implement it
  519. *
  520. * @param mixed $site_guid Optional site guid
  521. * @return bool
  522. */
  523. public function canActivate($site_guid = null) {
  524. if ($this->getPackage()) {
  525. $result = $this->getPackage()->isValid() && $this->getPackage()->checkDependencies();
  526. if (!$result) {
  527. $this->errorMsg = $this->getPackage()->getError();
  528. }
  529. return $result;
  530. }
  531. return false;
  532. }
  533. // activating and deactivating
  534. /**
  535. * Actives the plugin for the current site.
  536. *
  537. * @param mixed $site_guid Optional site GUID.
  538. * @return bool
  539. */
  540. public function activate($site_guid = null) {
  541. if ($this->isActive($site_guid)) {
  542. return false;
  543. }
  544. if (!$this->canActivate()) {
  545. return false;
  546. }
  547. // set in the db, now perform tasks and emit events
  548. if ($this->setStatus(true, $site_guid)) {
  549. // emit an event. returning false will make this not be activated.
  550. // we need to do this after it's been fully activated
  551. // or the deactivate will be confused.
  552. $params = array(
  553. 'plugin_id' => $this->getID(),
  554. 'plugin_entity' => $this,
  555. );
  556. $return = _elgg_services()->events->trigger('activate', 'plugin', $params);
  557. // if there are any on_enable functions, start the plugin now and run them
  558. // Note: this will not run re-run the init hooks!
  559. if ($return) {
  560. if ($this->canReadFile('activate.php')) {
  561. $flags = ELGG_PLUGIN_INCLUDE_START | ELGG_PLUGIN_REGISTER_CLASSES |
  562. ELGG_PLUGIN_REGISTER_LANGUAGES | ELGG_PLUGIN_REGISTER_VIEWS;
  563. $this->start($flags);
  564. $return = $this->includeFile('activate.php');
  565. }
  566. }
  567. if ($return === false) {
  568. $this->deactivate($site_guid);
  569. }
  570. return $return;
  571. }
  572. return false;
  573. }
  574. /**
  575. * Deactivates the plugin.
  576. *
  577. * @param mixed $site_guid Optional site GUID.
  578. * @return bool
  579. */
  580. public function deactivate($site_guid = null) {
  581. if (!$this->isActive($site_guid)) {
  582. return false;
  583. }
  584. // emit an event. returning false will cause this to not be deactivated.
  585. $params = array(
  586. 'plugin_id' => $this->getID(),
  587. 'plugin_entity' => $this,
  588. );
  589. $return = _elgg_services()->events->trigger('deactivate', 'plugin', $params);
  590. // run any deactivate code
  591. if ($return) {
  592. if ($this->canReadFile('deactivate.php')) {
  593. $return = $this->includeFile('deactivate.php');
  594. }
  595. }
  596. if ($return === false) {
  597. return false;
  598. } else {
  599. return $this->setStatus(false, $site_guid);
  600. }
  601. }
  602. /**
  603. * Start the plugin.
  604. *
  605. * @param int $flags Start flags for the plugin. See the constants in lib/plugins.php for details.
  606. * @return true
  607. * @throws PluginException
  608. */
  609. public function start($flags) {
  610. //if (!$this->canActivate()) {
  611. // return false;
  612. //}
  613. // include classes
  614. if ($flags & ELGG_PLUGIN_REGISTER_CLASSES) {
  615. $this->registerClasses();
  616. }
  617. // include start file
  618. if ($flags & ELGG_PLUGIN_INCLUDE_START) {
  619. $this->includeFile('start.php');
  620. }
  621. // include views
  622. if ($flags & ELGG_PLUGIN_REGISTER_VIEWS) {
  623. $this->registerViews();
  624. }
  625. // include languages
  626. if ($flags & ELGG_PLUGIN_REGISTER_LANGUAGES) {
  627. $this->registerLanguages();
  628. }
  629. return true;
  630. }
  631. // start helpers
  632. /**
  633. * Get the config object in a deprecation wrapper
  634. *
  635. * @return \Elgg\DeprecationWrapper
  636. */
  637. protected static function getConfigWrapper() {
  638. static $wrapper;
  639. if (null === $wrapper) {
  640. global $CONFIG;
  641. $warning = 'Do not rely on local $CONFIG being available in start.php';
  642. $wrapper = new \Elgg\DeprecationWrapper($CONFIG, $warning, "1.10");
  643. }
  644. return $wrapper;
  645. }
  646. /**
  647. * Includes one of the plugins files
  648. *
  649. * @param string $filename The name of the file
  650. *
  651. * @throws PluginException
  652. * @return mixed The return value of the included file (or 1 if there is none)
  653. */
  654. protected function includeFile($filename) {
  655. // This needs to be here to be backwards compatible for 1.0-1.7.
  656. // They expect the global config object to be available in start.php.
  657. if ($filename == 'start.php') {
  658. $CONFIG = self::getConfigWrapper();
  659. }
  660. $filepath = "$this->path/$filename";
  661. if (!$this->canReadFile($filename)) {
  662. $msg = _elgg_services()->translator->translate('ElggPlugin:Exception:CannotIncludeFile',
  663. array($filename, $this->getID(), $this->guid, $this->path));
  664. throw new \PluginException($msg);
  665. }
  666. return include $filepath;
  667. }
  668. /**
  669. * Checks whether a plugin file with the given name exists
  670. *
  671. * @param string $filename The name of the file
  672. * @return bool
  673. */
  674. protected function canReadFile($filename) {
  675. return is_readable($this->path . '/' . $filename);
  676. }
  677. /**
  678. * Registers the plugin's views
  679. *
  680. * @throws PluginException
  681. * @return void
  682. */
  683. protected function registerViews() {
  684. if (!_elgg_services()->views->registerPluginViews($this->path, $failed_dir)) {
  685. $msg = _elgg_services()->translator->translate('ElggPlugin:Exception:CannotRegisterViews',
  686. array($this->getID(), $this->guid, $failed_dir));
  687. throw new \PluginException($msg);
  688. }
  689. }
  690. /**
  691. * Registers the plugin's languages
  692. *
  693. * @throws PluginException
  694. * @return true
  695. */
  696. protected function registerLanguages() {
  697. $languages_path = "$this->path/languages";
  698. // don't need to have classes
  699. if (!is_dir($languages_path)) {
  700. return true;
  701. }
  702. // but need to have working ones.
  703. if (!_elgg_services()->translator->registerTranslations($languages_path)) {
  704. $msg = _elgg_services()->translator->translate('ElggPlugin:Exception:CannotRegisterLanguages',
  705. array($this->getID(), $this->guid, $languages_path));
  706. throw new \PluginException($msg);
  707. }
  708. return true;
  709. }
  710. /**
  711. * Registers the plugin's classes
  712. *
  713. * @throws PluginException
  714. * @return true
  715. */
  716. protected function registerClasses() {
  717. $classes_path = "$this->path/classes";
  718. if (is_dir($classes_path)) {
  719. _elgg_services()->autoloadManager->addClasses($classes_path);
  720. }
  721. return true;
  722. }
  723. /**
  724. * Get an attribute or private setting value
  725. *
  726. * @param string $name Name of the attribute or private setting
  727. * @return mixed
  728. */
  729. public function __get($name) {
  730. // rewrite for old and inaccurate plugin:setting
  731. if (strstr($name, 'plugin:setting:')) {
  732. $msg = 'Direct access of user settings is deprecated. Use ElggPlugin->getUserSetting()';
  733. elgg_deprecated_notice($msg, 1.8);
  734. $name = str_replace('plugin:setting:', '', $name);
  735. $name = _elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
  736. }
  737. // See if its in our base attribute
  738. if (array_key_exists($name, $this->attributes)) {
  739. return $this->attributes[$name];
  740. }
  741. // @todo clean below - getPrivateSetting() should return null now
  742. // No, so see if its in the private data store.
  743. // get_private_setting() returns false if it doesn't exist
  744. $meta = $this->getPrivateSetting($name);
  745. if ($meta === false) {
  746. // Can't find it, so return null
  747. return null;
  748. }
  749. return $meta;
  750. }
  751. /**
  752. * Get a value from private settings.
  753. *
  754. * @param string $name Name
  755. * @return mixed
  756. * @deprecated 1.9
  757. */
  758. public function get($name) {
  759. elgg_deprecated_notice("Use -> instead of get()", 1.9);
  760. return $this->__get($name);
  761. }
  762. /**
  763. * Set a value as private setting or attribute.
  764. *
  765. * Attributes include title and description.
  766. *
  767. * @param string $name Name of the attribute or private_setting
  768. * @param mixed $value Value to be set
  769. * @return void
  770. */
  771. public function __set($name, $value) {
  772. if (array_key_exists($name, $this->attributes)) {
  773. // Check that we're not trying to change the guid!
  774. if ((array_key_exists('guid', $this->attributes)) && ($name == 'guid')) {
  775. return;
  776. }
  777. $this->attributes[$name] = $value;
  778. } else {
  779. // to make sure we trigger the correct hooks
  780. $this->setSetting($name, $value);
  781. }
  782. }
  783. /**
  784. * Save a value as private setting or attribute.
  785. *
  786. * Attributes include title and description.
  787. *
  788. * @param string $name Name
  789. * @param mixed $value Value
  790. * @return bool
  791. */
  792. public function set($name, $value) {
  793. elgg_deprecated_notice("Use -> instead of set()", 1.9);
  794. $this->__set($name, $value);
  795. return true;
  796. }
  797. /**
  798. * Sets the plugin to active or inactive for $site_guid.
  799. *
  800. * @param bool $active Set to active or inactive
  801. * @param mixed $site_guid Int for specific site, null for current site.
  802. *
  803. * @return bool
  804. */
  805. private function setStatus($active, $site_guid = null) {
  806. if (!$this->guid) {
  807. return false;
  808. }
  809. if ($site_guid) {
  810. $site = get_entity($site_guid);
  811. if (!($site instanceof \ElggSite)) {
  812. return false;
  813. }
  814. } else {
  815. $site = _elgg_services()->configTable->get('site');
  816. }
  817. if ($active) {
  818. $result = add_entity_relationship($this->guid, 'active_plugin', $site->guid);
  819. } else {
  820. $result = remove_entity_relationship($this->guid, 'active_plugin', $site->guid);
  821. }
  822. _elgg_invalidate_plugins_provides_cache();
  823. return $result;
  824. }
  825. /**
  826. * Returns the last error message registered.
  827. *
  828. * @return string|null
  829. */
  830. public function getError() {
  831. return $this->errorMsg;
  832. }
  833. /**
  834. * Returns this plugin's \ElggPluginManifest object
  835. *
  836. * @return \ElggPluginManifest
  837. */
  838. public function getManifest() {
  839. if ($this->manifest instanceof \ElggPluginManifest) {
  840. return $this->manifest;
  841. }
  842. try {
  843. $this->manifest = $this->getPackage()->getManifest();
  844. } catch (Exception $e) {
  845. _elgg_services()->logger->warn("Failed to load manifest for plugin $this->guid. " . $e->getMessage());
  846. $this->errorMsg = $e->getmessage();
  847. }
  848. return $this->manifest;
  849. }
  850. /**
  851. * Returns this plugin's \ElggPluginPackage object
  852. *
  853. * @return \ElggPluginPackage
  854. */
  855. public function getPackage() {
  856. if ($this->package instanceof \ElggPluginPackage) {
  857. return $this->package;
  858. }
  859. try {
  860. $this->package = new \ElggPluginPackage($this->path, false);
  861. } catch (Exception $e) {
  862. _elgg_services()->logger->warn("Failed to load package for $this->guid. " . $e->getMessage());
  863. $this->errorMsg = $e->getmessage();
  864. }
  865. return $this->package;
  866. }
  867. }