Overview

Packages

  • ClipIt
    • clipit
      • api
    • urjc
      • backend
  • Elgg
    • Core
      • Access
      • Authentication
      • Cache
      • Caches
      • Core
      • DataMode
        • Site
      • DataModel
        • Annotations
        • Entities
        • Extender
        • File
        • Importable
        • Loggable
        • Notable
        • Object
        • User
      • DataStorage
      • Exception
      • Exceptions
        • Stub
      • FileStore
        • Disk
      • Groups
      • Helpers
      • HMAC
      • Memcache
      • Metadata
      • Navigation
      • ODD
      • Output
      • Plugins
        • Settings
      • Sessions
      • SocialModel
        • Friendable
        • Locatable
      • WebServicesAPI
      • Widgets
      • XML
      • XMLRPC
    • Exceptions
      • Stub
  • None
  • PHP

Classes

  • ElggPluginManifest
  • ElggPluginManifestParser
  • ElggPluginManifestParser17
  • ElggPluginManifestParser18
  • ElggPluginPackage
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Parses Elgg manifest.xml files.
  4:  *
  5:  * Normalizes the values from the ElggManifestParser object.
  6:  *
  7:  * This requires an ElggPluginManifestParser class implementation
  8:  * as $this->parser.
  9:  *
 10:  * To add new parser versions, name them ElggPluginManifestParserXX
 11:  * where XX is the version specified in the top-level <plugin_manifest>
 12:  * tag's XML namespace.
 13:  *
 14:  * @package    Elgg.Core
 15:  * @subpackage Plugins
 16:  * @since      1.8
 17:  */
 18: class ElggPluginManifest {
 19: 
 20:     /**
 21:      * The parser object
 22:      */
 23:     protected $parser;
 24: 
 25:     /**
 26:      * The root for plugin manifest namespaces.
 27:      * This is in the format http://www.elgg.org/plugin_manifest/<version>
 28:      */
 29:     protected $namespace_root = 'http://www.elgg.org/plugin_manifest/';
 30: 
 31:     /**
 32:      * The expected structure of a plugins requires element
 33:      */
 34:     private $depsStructPlugin = array(
 35:         'type' => '',
 36:         'name' => '',
 37:         'version' => '',
 38:         'comparison' => 'ge'
 39:     );
 40: 
 41:     /**
 42:      * The expected structure of a priority element
 43:      */
 44:     private $depsStructPriority = array(
 45:         'type' => '',
 46:         'priority' => '',
 47:         'plugin' => ''
 48:     );
 49: 
 50:     /*
 51:      * The expected structure of elgg_version and elgg_release requires element
 52:      */
 53:     private $depsStructElgg = array(
 54:         'type' => '',
 55:         'version' => '',
 56:         'comparison' => 'ge'
 57:     );
 58: 
 59:     /**
 60:      * The expected structure of a requires php_ini dependency element
 61:      */
 62:     private $depsStructPhpIni = array(
 63:         'type' => '',
 64:         'name' => '',
 65:         'value' => '',
 66:         'comparison' => '='
 67:     );
 68: 
 69:     /**
 70:      * The expected structure of a requires php_extension dependency element
 71:      */
 72:     private $depsStructPhpExtension = array(
 73:         'type' => '',
 74:         'name' => '',
 75:         'version' => '',
 76:         'comparison' => '='
 77:     );
 78: 
 79:     /**
 80:      * The expected structure of a conflicts depedency element
 81:      */
 82:     private $depsConflictsStruct = array(
 83:         'type' => '',
 84:         'name' => '',
 85:         'version' => '',
 86:         'comparison' => '='
 87:     );
 88: 
 89:     /**
 90:      * The expected structure of a provides dependency element.
 91:      */
 92:     private $depsProvidesStruct = array(
 93:         'type' => '',
 94:         'name' => '',
 95:         'version' => ''
 96:     );
 97: 
 98:     /**
 99:      * The expected structure of a screenshot element
100:      */
101:     private $screenshotStruct = array(
102:         'description' => '',
103:         'path' => ''
104:     );
105: 
106:     /**
107:      * The API version of the manifest.
108:      *
109:      * @var int
110:      */
111:     protected $apiVersion;
112: 
113:     /**
114:      * The optional plugin id this manifest belongs to.
115:      *
116:      * @var string
117:      */
118:     protected $pluginID;
119: 
120:     /**
121:      * Load a manifest file, XmlElement or path to manifest.xml file
122:      *
123:      * @param mixed  $manifest  A string, XmlElement, or path of a manifest file.
124:      * @param string $plugin_id Optional ID of the owning plugin. Used to
125:      *                          fill in some values automatically.
126:      */
127:     public function __construct($manifest, $plugin_id = null) {
128:         if ($plugin_id) {
129:             $this->pluginID = $plugin_id;
130:         }
131: 
132:         // see if we need to construct the xml object.
133:         if ($manifest instanceof ElggXMLElement) {
134:             $manifest_obj = $manifest;
135:         } else {
136:             if (substr(trim($manifest), 0, 1) == '<') {
137:                 // this is a string
138:                 $raw_xml = $manifest;
139:             } elseif (is_file($manifest)) {
140:                 // this is a file
141:                 $raw_xml = file_get_contents($manifest);
142:             }
143: 
144:             $manifest_obj = xml_to_object($raw_xml);
145:         }
146: 
147:         if (!$manifest_obj) {
148:             throw new PluginException(elgg_echo('PluginException:InvalidManifest',
149:                         array($this->getPluginID())));
150:         }
151: 
152:         // set manifest api version
153:         if (isset($manifest_obj->attributes['xmlns'])) {
154:             $namespace = $manifest_obj->attributes['xmlns'];
155:             $version = str_replace($this->namespace_root, '', $namespace);
156:         } else {
157:             $version = 1.7;
158:         }
159: 
160:         $this->apiVersion = $version;
161: 
162:         $parser_class_name = 'ElggPluginManifestParser' . str_replace('.', '', $this->apiVersion);
163: 
164:         // @todo currently the autoloader freaks out if a class doesn't exist.
165:         try {
166:             $class_exists = class_exists($parser_class_name);
167:         } catch (Exception $e) {
168:             $class_exists = false;
169:         }
170: 
171:         if ($class_exists) {
172:             $this->parser = new $parser_class_name($manifest_obj, $this);
173:         } else {
174:             throw new PluginException(elgg_echo('PluginException:NoAvailableParser',
175:                             array($this->apiVersion, $this->getPluginID())));
176:         }
177: 
178:         if (!$this->parser->parse()) {
179:             throw new PluginException(elgg_echo('PluginException:ParserError',
180:                         array($this->apiVersion, $this->getPluginID())));
181:         }
182: 
183:         return true;
184:     }
185: 
186:     /**
187:      * Returns the API version in use.
188:      *
189:      * @return int
190:      */
191:     public function getApiVersion() {
192:         return $this->apiVersion;
193:     }
194: 
195:     /**
196:      * Returns the plugin ID.
197:      *
198:      * @return string
199:      */
200:     public function getPluginID() {
201:         if ($this->pluginID) {
202:             return $this->pluginID;
203:         } else {
204:             return elgg_echo('unknown');
205:         }
206:     }
207: 
208:     /**
209:      * Returns the manifest array.
210:      *
211:      * Used for backward compatibility.  Specific
212:      * methods should be called instead.
213:      *
214:      * @return array
215:      */
216:     public function getManifest() {
217:         return $this->parser->getManifest();
218:     }
219: 
220:     /***************************************
221:      * Parsed and Normalized Manifest Data *
222:      ***************************************/
223: 
224:     /**
225:      * Returns the plugin name
226:      *
227:      * @return string
228:      */
229:     public function getName() {
230:         $name = $this->parser->getAttribute('name');
231: 
232:         if (!$name && $this->pluginID) {
233:             $name = ucwords(str_replace('_', ' ', $this->pluginID));
234:         }
235: 
236:         return $name;
237:     }
238: 
239: 
240:     /**
241:      * Return the description
242:      *
243:      * @return string
244:      */
245:     public function getDescription() {
246:         return $this->parser->getAttribute('description');
247:     }
248: 
249:     /**
250:      * Return the short description
251:      *
252:      * @return string
253:      */
254:     public function getBlurb() {
255:         $blurb = $this->parser->getAttribute('blurb');
256: 
257:         if (!$blurb) {
258:             $blurb = elgg_get_excerpt($this->getDescription());
259:         }
260: 
261:         return $blurb;
262:     }
263: 
264:     /**
265:      * Returns the license
266:      *
267:      * @return string
268:      */
269:     public function getLicense() {
270:         // license vs licence.  Use license.
271:         $en_us = $this->parser->getAttribute('license');
272:         if ($en_us) {
273:             return $en_us;
274:         } else {
275:             return $this->parser->getAttribute('licence');
276:         }
277:     }
278: 
279:     /**
280:      * Returns the repository url
281:      *
282:      * @return string
283:      */
284:     public function getRepositoryURL() {
285:         return $this->parser->getAttribute('repository');
286:     }
287: 
288:     /**
289:      * Returns the bug tracker page
290:      *
291:      * @return string
292:      */
293:     public function getBugTrackerURL() {
294:         return $this->parser->getAttribute('bugtracker');
295:     }
296: 
297:     /**
298:      * Returns the donations page
299:      *
300:      * @return string
301:      */
302:     public function getDonationsPageURL() {
303:         return $this->parser->getAttribute('donations');
304:     }
305: 
306:     /**
307:      * Returns the version of the plugin.
308:      *
309:      * @return float
310:      */
311:     public function getVersion() {
312:         return $this->parser->getAttribute('version');
313:     }
314: 
315:     /**
316:      * Returns the plugin author.
317:      *
318:      * @return string
319:      */
320:     public function getAuthor() {
321:         return $this->parser->getAttribute('author');
322:     }
323: 
324:     /**
325:      * Return the copyright
326:      *
327:      * @return string
328:      */
329:     public function getCopyright() {
330:         return $this->parser->getAttribute('copyright');
331:     }
332: 
333:     /**
334:      * Return the website
335:      *
336:      * @return string
337:      */
338:     public function getWebsite() {
339:         return $this->parser->getAttribute('website');
340:     }
341: 
342:     /**
343:      * Return the categories listed for this plugin
344:      *
345:      * @return array
346:      */
347:     public function getCategories() {
348:         $bundled_plugins = array('blog', 'bookmarks', 'categories',
349:             'custom_index', 'dashboard', 'developers', 'diagnostics',
350:             'embed', 'externalpages', 'file', 'garbagecollector',
351:             'groups', 'htmlawed', 'invitefriends', 'likes',
352:             'logbrowser', 'logrotate', 'members', 'messageboard',
353:             'messages', 'notifications', 'oauth_api', 'pages', 'profile',
354:             'reportedcontent', 'search', 'tagcloud', 'thewire', 'tinymce',
355:             'twitter', 'twitter_api', 'uservalidationbyemail', 'zaudio',
356:         );
357: 
358:         $cats = $this->parser->getAttribute('category');
359: 
360:         if (!$cats) {
361:             $cats = array();
362:         }
363: 
364:         if (in_array('bundled', $cats) && !in_array($this->getPluginID(), $bundled_plugins)) {
365:             unset($cats[array_search('bundled', $cats)]);
366:         }
367: 
368:         return $cats;
369:     }
370: 
371:     /**
372:      * Return the screenshots listed.
373:      *
374:      * @return array
375:      */
376:     public function getScreenshots() {
377:         $ss = $this->parser->getAttribute('screenshot');
378: 
379:         if (!$ss) {
380:             $ss = array();
381:         }
382: 
383:         $normalized = array();
384:         foreach ($ss as $s) {
385:             $normalized[] = $this->buildStruct($this->screenshotStruct, $s);
386:         }
387: 
388:         return $normalized;
389:     }
390: 
391:     /**
392:      * Return the list of provides by this plugin.
393:      *
394:      * @return array
395:      */
396:     public function getProvides() {
397:         // normalize for 1.7
398:         if ($this->getApiVersion() < 1.8) {
399:             $provides = array();
400:         } else {
401:             $provides = $this->parser->getAttribute('provides');
402:         }
403: 
404:         if (!$provides) {
405:             $provides = array();
406:         }
407: 
408:         // always provide ourself if we can
409:         if ($this->pluginID) {
410:             $provides[] = array(
411:                 'type' => 'plugin',
412:                 'name' => $this->getPluginID(),
413:                 'version' => $this->getVersion()
414:             );
415:         }
416: 
417:         $normalized = array();
418:         foreach ($provides as $provide) {
419:             $normalized[] = $this->buildStruct($this->depsProvidesStruct, $provide);
420:         }
421: 
422:         return $normalized;
423:     }
424: 
425:     /**
426:      * Returns the dependencies listed.
427:      *
428:      * @return array
429:      */
430:     public function getRequires() {
431:         // rewrite the 1.7 style elgg_version as a real requires.
432:         if ($this->apiVersion < 1.8) {
433:             $elgg_version = $this->parser->getAttribute('elgg_version');
434:             if ($elgg_version) {
435:                 $reqs = array(
436:                     array(
437:                         'type' => 'elgg_version',
438:                         'version' => $elgg_version,
439:                         'comparison' => 'ge'
440:                     )
441:                 );
442:             } else {
443:                 $reqs = array();
444:             }
445:         } else {
446:             $reqs = $this->parser->getAttribute('requires');
447:         }
448: 
449:         if (!$reqs) {
450:             $reqs = array();
451:         }
452: 
453:         $normalized = array();
454:         foreach ($reqs as $req) {
455:             $normalized[] = $this->normalizeDep($req);
456:         }
457: 
458:         return $normalized;
459:     }
460: 
461:     /**
462:      * Returns the suggests elements.
463:      *
464:      * @return array
465:      */
466:     public function getSuggests() {
467:         $suggests = $this->parser->getAttribute('suggests');
468: 
469:         if (!$suggests) {
470:             $suggests = array();
471:         }
472: 
473:         $normalized = array();
474:         foreach ($suggests as $suggest) {
475:             $normalized[] = $this->normalizeDep($suggest);
476:         }
477: 
478:         return $normalized;
479:     }
480: 
481:     /**
482:      * Normalizes a dependency array using the defined structs.
483:      * Can be used with either requires or suggests.
484:      *
485:      * @param array $dep A dependency array.
486:      * @return array The normalized deps array.
487:      */
488:     private function normalizeDep($dep) {
489:         switch ($dep['type']) {
490:             case 'elgg_version':
491:             case 'elgg_release':
492:                 $struct = $this->depsStructElgg;
493:                 break;
494: 
495:             case 'plugin':
496:                 $struct = $this->depsStructPlugin;
497:                 break;
498: 
499:             case 'priority':
500:                 $struct = $this->depsStructPriority;
501:                 break;
502: 
503:             case 'php_extension':
504:                 $struct = $this->depsStructPhpExtension;
505:                 break;
506: 
507:             case 'php_ini':
508:                 $struct = $this->depsStructPhpIni;
509: 
510:                 // also normalize boolean values
511:                 if (isset($dep['value'])) {
512:                     switch (strtolower($dep['value'])) {
513:                         case 'yes':
514:                         case 'true':
515:                         case 'on':
516:                         case 1:
517:                             $dep['value'] = 1;
518:                             break;
519: 
520:                         case 'no':
521:                         case 'false':
522:                         case 'off':
523:                         case 0:
524:                         case '':
525:                             $dep['value'] = 0;
526:                             break;
527:                     }
528:                 }
529:                 break;
530:             default:
531:                 // unrecognized so we just return the raw dependency
532:                 return $dep;
533:         }
534: 
535:         $normalized_dep = $this->buildStruct($struct, $dep);
536: 
537:         // normalize comparison operators
538:         if (isset($normalized_dep['comparison'])) {
539:             switch ($normalized_dep['comparison']) {
540:                 case '<':
541:                     $normalized_dep['comparison'] = 'lt';
542:                     break;
543: 
544:                 case '<=':
545:                     $normalized_dep['comparison'] = 'le';
546:                     break;
547: 
548:                 case '>':
549:                     $normalized_dep['comparison'] = 'gt';
550:                     break;
551: 
552:                 case '>=':
553:                     $normalized_dep['comparison'] = 'ge';
554:                     break;
555: 
556:                 case '==':
557:                 case 'eq':
558:                     $normalized_dep['comparison'] = '=';
559:                     break;
560: 
561:                 case '<>':
562:                 case 'ne':
563:                     $normalized_dep['comparison'] = '!=';
564:                     break;
565:             }
566:         }
567: 
568:         return $normalized_dep;
569:     }
570: 
571:     /**
572:      * Returns the conflicts listed
573:      *
574:      * @return array
575:      */
576:     public function getConflicts() {
577:         // normalize for 1.7
578:         if ($this->getApiVersion() < 1.8) {
579:             $conflicts = array();
580:         } else {
581:             $conflicts = $this->parser->getAttribute('conflicts');
582:         }
583: 
584:         if (!$conflicts) {
585:             $conflicts = array();
586:         }
587: 
588:         $normalized = array();
589: 
590:         foreach ($conflicts as $conflict) {
591:             $normalized[] = $this->buildStruct($this->depsConflictsStruct, $conflict);
592:         }
593: 
594:         return $normalized;
595:     }
596: 
597:     /**
598:      * Should this plugin be activated when Elgg is installed
599:      *
600:      *  @return bool
601:      */
602:     public function getActivateOnInstall() {
603:         $activate = $this->parser->getAttribute('activate_on_install');
604:         switch (strtolower($activate)) {
605:             case 'yes':
606:             case 'true':
607:             case 'on':
608:             case 1:
609:                 return true;
610: 
611:             case 'no':
612:             case 'false':
613:             case 'off':
614:             case 0:
615:             case '':
616:                 return false;
617:         }
618:     }
619: 
620:     /**
621:      * Normalizes an array into the structure specified
622:      *
623:      * @param array $struct The struct to normalize $element to.
624:      * @param array $array  The array
625:      *
626:      * @return array
627:      */
628:     protected function buildStruct(array $struct, array $array) {
629:         $return = array();
630: 
631:         foreach ($struct as $index => $default) {
632:             $return[$index] = elgg_extract($index, $array, $default);
633:         }
634: 
635:         return $return;
636:     }
637: 
638:     /**
639:      * Returns a category's friendly name. This can be localized by
640:      * defining the string 'admin:plugins:category:<category>'. If no
641:      * localization is found, returns the category with _ and - converted to ' '
642:      * and then ucwords()'d.
643:      *
644:      * @param str $category The category as defined in the manifest.
645:      * @return str A human-readable category
646:      */
647:     static public function getFriendlyCategory($category) {
648:         $cat_raw_string = "admin:plugins:category:$category";
649:         $cat_display_string = elgg_echo($cat_raw_string);
650:         if ($cat_display_string == $cat_raw_string) {
651:             $category = str_replace(array('-', '_'), ' ', $category);
652:             $cat_display_string = ucwords($category);
653:         }
654:         return $cat_display_string;
655:     }
656: }
657: 
API documentation generated by ApiGen 2.8.0