1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10:
11: class ElggPlugin extends ElggObject {
12: private $package;
13: private $manifest;
14:
15: private $path;
16: private $pluginID;
17: private $errorMsg = '';
18:
19: 20: 21: 22: 23:
24: protected function initializeAttributes() {
25: parent::initializeAttributes();
26:
27: $this->attributes['subtype'] = "plugin";
28:
29:
30: $this->access_id = ACCESS_PUBLIC;
31: }
32:
33: 34: 35: 36: 37: 38: 39: 40: 41: 42:
43: public function __construct($plugin) {
44: if (!$plugin) {
45: throw new PluginException(elgg_echo('PluginException:NullInstantiated'));
46: }
47:
48:
49:
50: if (is_numeric($plugin) || is_object($plugin)) {
51: parent::__construct($plugin);
52: $this->path = elgg_get_plugins_path() . $this->getID();
53: } else {
54: $plugin_path = elgg_get_plugins_path();
55:
56:
57:
58: if (strpos($plugin, $plugin_path) !== 0) {
59: $plugin = $plugin_path . $plugin;
60: }
61:
62:
63: $plugin = sanitise_filepath($plugin);
64: $this->path = $plugin;
65: $path_parts = explode('/', rtrim($plugin, '/'));
66: $plugin_id = array_pop($path_parts);
67: $this->pluginID = $plugin_id;
68:
69:
70: $existing_plugin = elgg_get_plugin_from_id($this->pluginID);
71: $existing_guid = null;
72:
73: if ($existing_plugin) {
74: $existing_guid = $existing_plugin->guid;
75: }
76:
77:
78: parent::__construct($existing_guid);
79: }
80:
81: _elgg_cache_plugin_by_id($this);
82: }
83:
84: 85: 86: 87: 88: 89:
90: public function save() {
91:
92: $site = get_config('site');
93: $this->attributes['site_guid'] = $site->guid;
94: $this->attributes['owner_guid'] = $site->guid;
95: $this->attributes['container_guid'] = $site->guid;
96: $this->attributes['title'] = $this->pluginID;
97:
98: if (parent::save()) {
99:
100: $priority = $this->getPriority();
101: if ($priority === FALSE || $priority === NULL) {
102: return $this->setPriority('last');
103: }
104: } else {
105: return false;
106: }
107: }
108:
109:
110:
111:
112: 113: 114: 115: 116:
117: public function getID() {
118: return $this->title;
119: }
120:
121: 122: 123: 124: 125: 126:
127: public function getFriendlyName() {
128: $manifest = $this->getManifest();
129: if ($manifest) {
130: return $manifest->getName();
131: }
132:
133: return $this->getID();
134: }
135:
136: 137: 138: 139: 140:
141: public function getPath() {
142: return sanitise_filepath($this->path);
143: }
144:
145: 146: 147: 148: 149: 150:
151: public function setID($id) {
152: return $this->attributes['title'] = $id;
153: }
154:
155: 156: 157: 158: 159:
160: public function getAvailableTextFiles() {
161: $filenames = $this->getPackage()->getTextFilenames();
162:
163: $files = array();
164: foreach ($filenames as $filename) {
165: if ($this->canReadFile($filename)) {
166: $files[$filename] = "$this->path/$filename";
167: }
168: }
169:
170: return $files;
171: }
172:
173:
174:
175: 176: 177: 178: 179:
180: public function getPriority() {
181: $name = elgg_namespace_plugin_private_setting('internal', 'priority');
182: return $this->$name;
183: }
184:
185: 186: 187: 188: 189: 190: 191: 192: 193:
194: public function setPriority($priority, $site_guid = null) {
195: if (!$this->guid) {
196: return false;
197: }
198:
199: $db_prefix = get_config('dbprefix');
200: $name = elgg_namespace_plugin_private_setting('internal', 'priority');
201:
202: $old_priority = (int) $this->getPriority();
203: $old_priority = (!$old_priority) ? 1 : $old_priority;
204: $max_priority = elgg_get_max_plugin_priority();
205:
206:
207:
208: if ($priority === '+1') {
209: $priority = $old_priority + 1;
210: } elseif ($priority === '-1') {
211: $priority = $old_priority - 1;
212: } elseif ($priority === 'first') {
213: $priority = 1;
214: } elseif ($priority === 'last') {
215: $priority = $max_priority;
216: }
217:
218:
219: if ($priority > 0) {
220: if (!is_numeric($priority)) {
221: return false;
222: }
223:
224:
225: if ($priority > $max_priority) {
226: $priority = $max_priority;
227: }
228:
229:
230: if ($priority < 1) {
231: $priority = 1;
232: }
233:
234: if ($priority > $old_priority) {
235: $op = '-';
236: $where = "CAST(value as unsigned) BETWEEN $old_priority AND $priority";
237: } else {
238: $op = '+';
239: $where = "CAST(value as unsigned) BETWEEN $priority AND $old_priority";
240: }
241:
242:
243: $q = "UPDATE {$db_prefix}private_settings
244: SET value = CAST(value as unsigned) $op 1
245: WHERE entity_guid != $this->guid
246: AND name = '$name'
247: AND $where";
248:
249: if (!update_data($q)) {
250: return false;
251: }
252:
253:
254: if ($this->set($name, $priority)) {
255: return true;
256: } else {
257: return false;
258: }
259: }
260:
261: return false;
262: }
263:
264:
265:
266:
267: 268: 269: 270: 271: 272:
273: public function getSetting($name) {
274: return $this->$name;
275: }
276:
277: 278: 279: 280: 281: 282: 283:
284: public function getAllSettings() {
285: if (!$this->guid) {
286: return false;
287: }
288:
289: $db_prefix = elgg_get_config('dbprefix');
290:
291: $us_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
292: $is_prefix = elgg_namespace_plugin_private_setting('internal', '', $this->getID());
293:
294:
295: $q = "SELECT * FROM {$db_prefix}private_settings
296: WHERE entity_guid = $this->guid
297: AND name NOT LIKE '$us_prefix%'
298: AND name NOT LIKE '$is_prefix%'";
299:
300: $private_settings = get_data($q);
301:
302: if ($private_settings) {
303: $return = array();
304:
305: foreach ($private_settings as $setting) {
306: $return[$setting->name] = $setting->value;
307: }
308:
309: return $return;
310: }
311:
312: return false;
313: }
314:
315: 316: 317: 318: 319: 320: 321: 322: 323: 324:
325: public function setSetting($name, $value) {
326: if (!$this->guid) {
327: return false;
328: }
329:
330: return $this->set($name, $value);
331: }
332:
333: 334: 335: 336: 337: 338: 339:
340: public function unsetSetting($name) {
341: return remove_private_setting($this->guid, $name);
342: }
343:
344: 345: 346: 347: 348: 349: 350:
351: public function unsetAllSettings() {
352: $db_prefix = get_config('dbprefix');
353: $ps_prefix = elgg_namespace_plugin_private_setting('setting', '');
354:
355: $q = "DELETE FROM {$db_prefix}private_settings
356: WHERE entity_guid = $this->guid
357: AND name NOT LIKE '$ps_prefix%'";
358:
359: return delete_data($q);
360: }
361:
362:
363:
364:
365: 366: 367: 368: 369: 370: 371: 372:
373: public function getUserSetting($name, $user_guid = null) {
374: $user_guid = (int)$user_guid;
375:
376: if ($user_guid) {
377: $user = get_entity($user_guid);
378: } else {
379: $user = elgg_get_logged_in_user_entity();
380: }
381:
382: if (!($user instanceof ElggUser)) {
383: return false;
384: }
385:
386: $name = elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
387: return get_private_setting($user->guid, $name);
388: }
389:
390: 391: 392: 393: 394: 395: 396: 397:
398: public function getAllUserSettings($user_guid = null) {
399: $user_guid = (int)$user_guid;
400:
401: if ($user_guid) {
402: $user = get_entity($user_guid);
403: } else {
404: $user = elgg_get_logged_in_user_entity();
405: }
406:
407: if (!($user instanceof ElggUser)) {
408: return false;
409: }
410:
411: $db_prefix = elgg_get_config('dbprefix');
412:
413: $ps_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
414: $ps_prefix_len = strlen($ps_prefix);
415:
416:
417: $q = "SELECT * FROM {$db_prefix}private_settings
418: WHERE entity_guid = {$user->guid}
419: AND name LIKE '$ps_prefix%'";
420:
421: $private_settings = get_data($q);
422:
423: if ($private_settings) {
424: $return = array();
425:
426: foreach ($private_settings as $setting) {
427: $name = substr($setting->name, $ps_prefix_len);
428: $value = $setting->value;
429:
430: $return[$name] = $value;
431: }
432:
433: return $return;
434: }
435:
436: return false;
437: }
438:
439: 440: 441: 442: 443: 444: 445: 446: 447:
448: public function setUserSetting($name, $value, $user_guid = null) {
449: $user_guid = (int)$user_guid;
450:
451: if ($user_guid) {
452: $user = get_entity($user_guid);
453: } else {
454: $user = elgg_get_logged_in_user_entity();
455: }
456:
457: if (!($user instanceof ElggUser)) {
458: return false;
459: }
460:
461:
462:
463: $value = elgg_trigger_plugin_hook('usersetting', 'plugin', array(
464: 'user' => $user,
465: 'plugin' => $this,
466: 'plugin_id' => $this->getID(),
467: 'name' => $name,
468: 'value' => $value
469: ), $value);
470:
471:
472: $name = elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
473:
474: return set_private_setting($user->guid, $name, $value);
475: }
476:
477:
478: 479: 480: 481: 482: 483: 484:
485: public function unsetUserSetting($name, $user_guid = null) {
486: $user_guid = (int)$user_guid;
487:
488: if ($user_guid) {
489: $user = get_entity($user_guid);
490: } else {
491: $user = elgg_get_logged_in_user_entity();
492: }
493:
494: if (!($user instanceof ElggUser)) {
495: return false;
496: }
497:
498:
499: $name = elgg_namespace_plugin_private_setting('user_setting', $name, $this->getID());
500:
501: return remove_private_setting($user->guid, $name);
502: }
503:
504: 505: 506: 507: 508: 509: 510: 511: 512:
513: public function unsetAllUserSettings($user_guid) {
514: $db_prefix = get_config('dbprefix');
515: $ps_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
516:
517: $q = "DELETE FROM {$db_prefix}private_settings
518: WHERE entity_guid = $user_guid
519: AND name LIKE '$ps_prefix%'";
520:
521: return delete_data($q);
522: }
523:
524: 525: 526: 527: 528: 529: 530: 531:
532: public function () {
533: $db_prefix = get_config('dbprefix');
534: $ps_prefix = elgg_namespace_plugin_private_setting('user_setting', '', $this->getID());
535:
536: $q = "DELETE FROM {$db_prefix}private_settings
537: WHERE name LIKE '$ps_prefix%'";
538:
539: return delete_data($q);
540: }
541:
542:
543:
544:
545: 546: 547: 548: 549: 550: 551: 552:
553: public function isValid() {
554: if (!$this->getID()) {
555: $this->errorMsg = elgg_echo('ElggPlugin:NoId', array($this->guid));
556: return false;
557: }
558:
559: if (!$this->getPackage() instanceof ElggPluginPackage) {
560: $this->errorMsg = elgg_echo('ElggPlugin:NoPluginPackagePackage', array($this->getID(), $this->guid));
561: return false;
562: }
563:
564: if (!$this->getPackage()->isValid()) {
565: $this->errorMsg = $this->getPackage()->getError();
566: return false;
567: }
568:
569: return true;
570: }
571:
572: 573: 574: 575: 576: 577:
578: public function isActive($site_guid = null) {
579: if (!$this->guid) {
580: return false;
581: }
582:
583: if ($site_guid) {
584: $site = get_entity($site_guid);
585: } else {
586: $site = get_config('site');
587: }
588:
589: if (!($site instanceof ElggSite)) {
590: return false;
591: }
592:
593: return check_entity_relationship($this->guid, 'active_plugin', $site->guid);
594: }
595:
596: 597: 598: 599: 600: 601: 602: 603: 604:
605: public function canActivate($site_guid = null) {
606: if ($this->getPackage()) {
607: $result = $this->getPackage()->isValid() && $this->getPackage()->checkDependencies();
608: if (!$result) {
609: $this->errorMsg = $this->getPackage()->getError();
610: }
611:
612: return $result;
613: }
614:
615: return false;
616: }
617:
618:
619:
620:
621: 622: 623: 624: 625: 626:
627: public function activate($site_guid = null) {
628: if ($this->isActive($site_guid)) {
629: return false;
630: }
631:
632: if (!$this->canActivate()) {
633: return false;
634: }
635:
636:
637: if ($this->setStatus(true, $site_guid)) {
638:
639:
640:
641: $params = array(
642: 'plugin_id' => $this->pluginID,
643: 'plugin_entity' => $this
644: );
645:
646: $return = elgg_trigger_event('activate', 'plugin', $params);
647:
648:
649:
650: if ($return) {
651: if ($this->canReadFile('activate.php')) {
652: $flags = ELGG_PLUGIN_INCLUDE_START | ELGG_PLUGIN_REGISTER_CLASSES |
653: ELGG_PLUGIN_REGISTER_LANGUAGES | ELGG_PLUGIN_REGISTER_VIEWS;
654:
655: $this->start($flags);
656:
657: $return = $this->includeFile('activate.php');
658: }
659: }
660:
661: if ($return === false) {
662: $this->deactivate($site_guid);
663: }
664:
665: return $return;
666: }
667:
668: return false;
669: }
670:
671: 672: 673: 674: 675: 676:
677: public function deactivate($site_guid = null) {
678: if (!$this->isActive($site_guid)) {
679: return false;
680: }
681:
682:
683: $params = array(
684: 'plugin_id' => $this->pluginID,
685: 'plugin_entity' => $this
686: );
687:
688: $return = elgg_trigger_event('deactivate', 'plugin', $params);
689:
690:
691: if ($return) {
692: if ($this->canReadFile('deactivate.php')) {
693: $return = $this->includeFile('deactivate.php');
694: }
695: }
696:
697: if ($return === false) {
698: return false;
699: } else {
700: return $this->setStatus(false, $site_guid);
701: }
702: }
703:
704: 705: 706: 707: 708: 709: 710:
711: public function start($flags) {
712:
713:
714:
715:
716:
717: if ($flags & ELGG_PLUGIN_REGISTER_CLASSES) {
718: $this->registerClasses();
719: }
720:
721:
722: if ($flags & ELGG_PLUGIN_INCLUDE_START) {
723: $this->includeFile('start.php');
724: }
725:
726:
727: if ($flags & ELGG_PLUGIN_REGISTER_VIEWS) {
728: $this->registerViews();
729: }
730:
731:
732: if ($flags & ELGG_PLUGIN_REGISTER_LANGUAGES) {
733: $this->registerLanguages();
734: }
735:
736: return true;
737: }
738:
739:
740:
741:
742: 743: 744: 745: 746: 747: 748: 749:
750: protected function includeFile($filename) {
751:
752:
753: if ($filename == 'start.php') {
754: global $CONFIG;
755: }
756:
757: $filepath = "$this->path/$filename";
758:
759: if (!$this->canReadFile($filename)) {
760: $msg = elgg_echo('ElggPlugin:Exception:CannotIncludeFile',
761: array($filename, $this->getID(), $this->guid, $this->path));
762: throw new PluginException($msg);
763: }
764:
765: return include $filepath;
766: }
767:
768: 769: 770: 771: 772: 773:
774: protected function canReadFile($filename) {
775: return is_readable($this->path . '/' . $filename);
776: }
777:
778: 779: 780: 781: 782: 783:
784: protected function registerViews() {
785: $view_dir = "$this->path/views/";
786:
787:
788: if (!is_dir($view_dir)) {
789: return true;
790: }
791:
792:
793: $handle = opendir($view_dir);
794: if (!$handle) {
795: $msg = elgg_echo('ElggPlugin:Exception:CannotRegisterViews',
796: array($this->getID(), $this->guid, $view_dir));
797: throw new PluginException($msg);
798: }
799:
800: while (FALSE !== ($view_type = readdir($handle))) {
801: $view_type_dir = $view_dir . $view_type;
802:
803: if ('.' !== substr($view_type, 0, 1) && is_dir($view_type_dir)) {
804: if (autoregister_views('', $view_type_dir, $view_dir, $view_type)) {
805: elgg_register_viewtype($view_type);
806: } else {
807: $msg = elgg_echo('ElggPlugin:Exception:CannotRegisterViews',
808: array($this->getID(), $view_type_dir));
809: throw new PluginException($msg);
810: }
811: }
812: }
813:
814: return true;
815: }
816:
817: 818: 819: 820: 821: 822:
823: protected function registerLanguages() {
824: $languages_path = "$this->path/languages";
825:
826:
827: if (!is_dir($languages_path)) {
828: return true;
829: }
830:
831:
832: if (!register_translations($languages_path)) {
833: $msg = elgg_echo('ElggPlugin:Exception:CannotRegisterLanguages',
834: array($this->getID(), $this->guid, $languages_path));
835: throw new PluginException($msg);
836: }
837:
838: return true;
839: }
840:
841: 842: 843: 844: 845: 846:
847: protected function registerClasses() {
848: $classes_path = "$this->path/classes";
849:
850:
851: if (!is_dir($classes_path)) {
852: return true;
853: }
854:
855: elgg_register_classes($classes_path);
856:
857: return true;
858: }
859:
860:
861:
862:
863: 864: 865: 866: 867: 868: 869:
870: public function get($name) {
871:
872: if (strstr($name, 'plugin:setting:')) {
873: $msg = 'Direct access of user settings is deprecated. Use ElggPlugin->getUserSetting()';
874: elgg_deprecated_notice($msg, 1.8);
875: $name = str_replace('plugin:setting:', '', $name);
876: $name = elgg_namespace_plugin_private_setting('user_setting', $name);
877: }
878:
879:
880: if (array_key_exists($name, $this->attributes)) {
881: return $this->attributes[$name];
882: }
883:
884:
885:
886: $meta = $this->getPrivateSetting($name);
887:
888: if ($meta === false) {
889:
890: return NULL;
891: }
892:
893: return $meta;
894: }
895:
896: 897: 898: 899: 900: 901: 902: 903: 904: 905:
906: public function set($name, $value) {
907: if (array_key_exists($name, $this->attributes)) {
908:
909: if ((array_key_exists('guid', $this->attributes)) && ($name == 'guid')) {
910: return false;
911: }
912:
913: $this->attributes[$name] = $value;
914:
915: return true;
916: } else {
917:
918: $value = elgg_trigger_plugin_hook('setting', 'plugin', array(
919: 'plugin_id' => $this->pluginID,
920: 'plugin' => $this,
921: 'name' => $name,
922: 'value' => $value
923: ), $value);
924:
925: return $this->setPrivateSetting($name, $value);
926: }
927: }
928:
929: 930: 931: 932: 933: 934: 935: 936:
937: private function setStatus($active, $site_guid = null) {
938: if (!$this->guid) {
939: return false;
940: }
941:
942: if ($site_guid) {
943: $site = get_entity($site_guid);
944:
945: if (!($site instanceof ElggSite)) {
946: return false;
947: }
948: } else {
949: $site = get_config('site');
950: }
951:
952: if ($active) {
953: return add_entity_relationship($this->guid, 'active_plugin', $site->guid);
954: } else {
955: return remove_entity_relationship($this->guid, 'active_plugin', $site->guid);
956: }
957: }
958:
959: 960: 961: 962: 963:
964: public function getError() {
965: return $this->errorMsg;
966: }
967:
968: 969: 970: 971: 972:
973: public function getManifest() {
974: if ($this->manifest instanceof ElggPluginManifest) {
975: return $this->manifest;
976: }
977:
978: try {
979: $this->manifest = $this->getPackage()->getManifest();
980: } catch (Exception $e) {
981: elgg_log("Failed to load manifest for plugin $this->guid. " . $e->getMessage(), 'WARNING');
982: $this->errorMsg = $e->getmessage();
983: }
984:
985: return $this->manifest;
986: }
987:
988: 989: 990: 991: 992:
993: public function getPackage() {
994: if ($this->package instanceof ElggPluginPackage) {
995: return $this->package;
996: }
997:
998: try {
999: $this->package = new ElggPluginPackage($this->path, false);
1000: } catch (Exception $e) {
1001: elgg_log("Failed to load package for $this->guid. " . $e->getMessage(), 'WARNING');
1002: $this->errorMsg = $e->getmessage();
1003: }
1004:
1005: return $this->package;
1006: }
1007: }
1008: