Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • PHP
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SIWECOS
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • PimPlugin
  • PimPluginArchiveExtractor
  • PimPluginCollection
  • PimPluginRelations
  • PimPluginRelationsCollection
  • PimPluginSetup
  • PimPluginSetupInstall
  • PimPluginSetupStatus
  • PimPluginSetupUninstall
  • PimPluginSetupUpdate
  • PimPluginViewDependencies
  • PimPluginViewNavSub
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3:  * This file contains abstract class for CONTENIDO plugins
  4:  *
  5:  * @package Plugin
  6:  * @subpackage PluginManager
  7:  * @author Frederic Schneider
  8:  * @copyright four for business AG <www.4fb.de>
  9:  * @license http://www.contenido.org/license/LIZENZ.txt
 10:  * @link http://www.4fb.de
 11:  * @link http://www.contenido.org
 12:  */
 13: 
 14: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 15: 
 16: /**
 17:  * Standard class for Plugin Manager (PIM)
 18:  *
 19:  * @package Plugin
 20:  * @subpackage PluginManager
 21:  * @author frederic.schneider
 22:  */
 23: class PimPluginSetup {
 24:     /**
 25:      * File name of Xml configuration file for plugins
 26:      */
 27:     const PLUGIN_XML_FILENAME = "plugin.xml";
 28:     /**
 29:      * Specific sql prefix
 30:      */
 31:     const SQL_PREFIX = "!PREFIX!";
 32: 
 33:     /**
 34:      * Initializing variables
 35:      * Variable for installation / update mode:
 36:      * Extracted or uploaded file?
 37:      *
 38:      * @var int
 39:      */
 40:     public static $mode = 0;
 41: 
 42:     /**
 43:      * @var cGuiPage
 44:      */
 45:     protected static $_GuiPage;
 46: 
 47:     /**
 48:      * @var PimPluginArchiveExtractor
 49:      */
 50:     protected static $_PimPluginArchiveExtractor;
 51: 
 52:     /**
 53:      * Help variable.
 54:      * If this variable is true PIM does not run uninstall and install
 55:      * sql file. Standard value: false (update sql file does not exist)
 56:      *
 57:      * @var bool
 58:      */
 59:     private static $_updateSqlFileExist = false;
 60: 
 61:     /**
 62:      * Xml variables
 63:      * General informations of plugin
 64:      *
 65:      * @var SimpleXMLElement
 66:      */
 67:     public static $XmlGeneral;
 68: 
 69:     /**
 70:      * Plugin requirements
 71:      *
 72:      * @var SimpleXMLElement
 73:      */
 74:     public static $XmlRequirements;
 75: 
 76:     /**
 77:      * Plugin dependencies
 78:      *
 79:      * @var SimpleXMLElement
 80:      */
 81:     public static $XmlDependencies;
 82: 
 83:     /**
 84:      * CONTENIDO areas: *_area
 85:      *
 86:      * @var SimpleXMLElement
 87:      */
 88:     public static $XmlArea;
 89: 
 90:     /**
 91:      * CONTENIDO actions: *_actions
 92:      *
 93:      * @var SimpleXMLElement
 94:      */
 95:     public static $XmlActions;
 96: 
 97:     /**
 98:      * CONTENIDO frames: *_frame_files and *_files
 99:      *
100:      * @var SimpleXMLElement
101:      */
102:     public static $XmlFrames;
103: 
104:     /**
105:      * CONTENIDO main navigations: *_nav_main
106:      *
107:      * @var SimpleXMLElement
108:      */
109:     public static $XmlNavMain;
110: 
111:     /**
112:      * CONTENIDO sub navigations: *_nav_sub
113:      *
114:      * @var SimpleXMLElement
115:      */
116:     public static $XmlNavSub;
117: 
118:     /**
119:      * CONTENIDO content types: *_type
120:      *
121:      * @var SimpleXMLElement
122:      */
123:     public static $XmlContentType;
124: 
125:     /**
126:      * Id of selected/new plugin
127:      *
128:      * @var int
129:      */
130:     protected static $_pluginId = 0;
131: 
132:     /**
133:      * Name of selected plugin
134:      *
135:      * @var string
136:      */
137:     protected static $_pluginName;
138: 
139:     // GET and SET methods for installation routine
140: 
141:     /**
142:      * Set method for installation / update mode
143:      * Mode 1: Plugin is already extracted
144:      * Mode 2: Plugin is uploaded
145:      *
146:      * @param string $mode
147:      */
148:     public static function setMode($mode) {
149:         switch ($mode) {
150:             case 'extracted':
151:                 self::$mode = 1;
152:                 break;
153:             case 'uploaded':
154:                 self::$mode = 2;
155:                 break;
156:             case 'uninstall':
157:                 self::$mode = 3;
158:                 break;
159:             case 'update':
160:                 self::$mode = 4;
161:                 break;
162:         }
163:     }
164: 
165:     /**
166:      * Set method for cGuiPage class
167:      *
168:      * @param cGuiPage $page
169:      *
170:      * @return cGuiPage
171:      */
172:     public function setPageClass($page) {
173:         return self::$_GuiPage = $page;
174:     }
175: 
176:     /**
177:      * Set method to change updateSqlFileExist variable
178:      *
179:      * @param bool $value
180:      */
181:     protected function _setUpdateSqlFileExist($value) {
182:         self::$_updateSqlFileExist = cSecurity::toBoolean($value);
183:     }
184: 
185:     /**
186:      * Initialzing and set variable for PimPluginArchiveExtractor class
187:      *
188:      * @param string $tempArchiveNewPath Path to Zip archive
189:      * @param string $tempArchiveName Name of Zip archive
190:      * @return PimPluginArchiveExtractor
191:      */
192:     protected static function _setPimPluginArchiveExtractor($tempArchiveNewPath, $tempArchiveName) {
193:         return self::$_PimPluginArchiveExtractor = new PimPluginArchiveExtractor($tempArchiveNewPath, $tempArchiveName);
194:     }
195: 
196:     /**
197:      * Set temporary xml content to static variables
198:      *
199:      * @param SimpleXMLElement $xml
200:      */
201:     private function _setXml($xml) {
202: 
203:         // General plugin informations
204:         self::$XmlGeneral = $xml->general;
205: 
206:         // Plugin requirements
207:         self::$XmlRequirements = $xml->requirements;
208: 
209:         // Plugin dependencies
210:         self::$XmlDependencies = $xml->dependencies;
211: 
212:         // CONTENIDO areas: *_area
213:         self::$XmlArea = $xml->contenido->areas;
214: 
215:         // CONTENIDO actions: *_actions
216:         self::$XmlActions = $xml->contenido->actions;
217: 
218:         // CONTENIDO frames: *_frame_files and *_files
219:         self::$XmlFrames = $xml->contenido->frames;
220: 
221:         // CONTENIDO main navigations: *_nav_main
222:         self::$XmlNavMain = $xml->contenido->nav_main;
223: 
224:         // CONTENIDO sub navigations: *_nav_sub
225:         self::$XmlNavSub = $xml->contenido->nav_sub;
226: 
227:         // CONTENIDO Content Types: *_type
228:         self::$XmlContentType = $xml->content_types;
229:     }
230: 
231:     /**
232:      * Set method for PluginId
233:      *
234:      * @param int $pluginId
235:      *
236:      * @return int
237:      */
238:     public function setPluginId($pluginId = 0) {
239:         return self::$_pluginId = $pluginId;
240:     }
241: 
242:     /**
243:      * Set method for PluginName
244:      *
245:      * @param string $pluginName
246:      *
247:      * @return string
248:      */
249:     public function setPluginName($pluginName = '') {
250:         return self::$_pluginName = $pluginName;
251:     }
252: 
253:     /**
254:      * Get method for installation / update mode
255:      *
256:      * @return int
257:      */
258:     public static function getMode() {
259:         return self::$mode;
260:     }
261: 
262:     /**
263:      * Get method for PluginId
264:      *
265:      * @return int
266:      */
267:     protected static function _getPluginId() {
268:         return self::$_pluginId;
269:     }
270: 
271:     /**
272:      * Get methos for PluginName
273:      *
274:      * @return string
275:      */
276:     protected static function _getPluginName() {
277:         return self::$_pluginName;
278:     }
279: 
280:     /**
281:      * Set method for updateSqlFileExist variable
282:      *
283:      * @return bool
284:      */
285:     protected function _getUpdateSqlFileExist() {
286:         return self::$_updateSqlFileExist;
287:     }
288: 
289:     // Help methods
290: 
291:     /**
292:      * checkXml
293:      * Load plugin datas and run Xml checks
294:      *
295:      * @throws cException
296:      */
297:     public function checkXml() {
298: 
299:         $cfg = cRegistry::getConfig();
300: 
301:         if (self::getMode() == 1) { // Plugin is already extracted
302:             $XmlData = file_get_contents($cfg['path']['contenido'] . $cfg['path']['plugins'] . cSecurity::escapeString($_GET['pluginFoldername']) . DIRECTORY_SEPARATOR . self::PLUGIN_XML_FILENAME);
303:         } elseif (self::getMode() == 2 || self::getMode() == 4) {
304:             // Plugin is uploaded / Update mode
305: 
306:             // Path to CONTENIDO temp dir
307:             $tempArchiveNewPath = $cfg['path']['frontend'] . DIRECTORY_SEPARATOR . $cfg['path']['temp'];
308: 
309:             // Check if temp directory exists, otherwise try to create it
310:             if (!cDirHandler::exists($tempArchiveNewPath)) {
311:                 $success = cDirHandler::create($tempArchiveNewPath);
312: 
313:                 // If PIM can not create a temporary directory (if it does not exists), throw an error message
314:                 if (!$success) {
315:                     self::error(sprintf(i18n('Plugin Manager can not found a temporary CONTENIDO directory. Also it is not possible to create a temporary directory at <em>%s</em>. You have to create it manualy.', 'pim'), $tempArchiveNewPath));
316:                     return;
317:                 }
318:             }
319: 
320:             // Name of uploaded Zip archive
321:             $tempArchiveName = cSecurity::escapeString($_FILES['package']['name']);
322: 
323:             // Move temporary archive files into CONTENIDO temp dir
324:             move_uploaded_file($_FILES['package']['tmp_name'], $tempArchiveNewPath . $tempArchiveName);
325: 
326:             // Initializing plugin archive extractor
327:             try {
328:                 self::_setPimPluginArchiveExtractor($tempArchiveNewPath, $tempArchiveName);
329:             } catch (cException $e) {
330:                 self::$_PimPluginArchiveExtractor->destroyTempFiles();
331:             }
332: 
333:             // Check valid Zip archive
334:             $this->checkZip();
335: 
336:             // Get plugin.xml informations
337:             $XmlData = self::$_PimPluginArchiveExtractor->extractArchiveFileToVariable(self::PLUGIN_XML_FILENAME);
338:         }
339: 
340:         // Check and set plugin.xml
341:         if ($this->validXml($XmlData) === true) {
342:             $this->_setXml(simplexml_load_string($XmlData));
343:         } else {
344:             self::error(i18n('Invalid Xml document. Please contact the plugin author.', 'pim'));
345:             return;
346:         }
347:     }
348: 
349:     /**
350:      * Check dependencies to other plugins (dependencies-Tag at plugin.xml)
351:      * Global function for uninstall and status mode
352:      * Install mode uses an own dependencies function
353:      *
354:      * @return bool
355:      *
356:      * @throws cInvalidArgumentException
357:      */
358:     public function checkDependencies() {
359: 
360:         // Initializings
361:         $cfg = cRegistry::getConfig();
362:         $pluginsDir = $cfg['path']['contenido'] . $cfg['path']['plugins'];
363: 
364:         // Get uuid from plugin to uninstall
365:         $this->_PimPluginCollection->setWhere('idplugin', self::_getPluginId());
366:         $this->_PimPluginCollection->query();
367:         $pimPluginSql = $this->_PimPluginCollection->next();
368:         $uuidUninstall = $pimPluginSql->get('uuid');
369: 
370:         // Reset query so we can use PimPluginCollection later again...
371:         $this->_PimPluginCollection->resetQuery();
372: 
373:         // Read all dirs
374:         $dirs = cDirHandler::read($pluginsDir);
375:         foreach ($dirs as $dirname) {
376: 
377:             // Skip plugin if it has no plugin.xml file
378:             if (!cFileHandler::exists($pluginsDir . $dirname . DIRECTORY_SEPARATOR . self::PLUGIN_XML_FILENAME)) {
379:                 continue;
380:             }
381: 
382:             // Read plugin.xml files from existing plugins at contenido/plugins dir
383:             $tempXmlContent = cFileHandler::read($pluginsDir . $dirname . DIRECTORY_SEPARATOR . self::PLUGIN_XML_FILENAME);
384: 
385:             // Write plugin.xml content into temporary variable
386:             $tempXml = simplexml_load_string($tempXmlContent);
387: 
388:             $dependenciesCount = count($tempXml->dependencies);
389:             for ($i = 0; $i < $dependenciesCount; $i++) {
390: 
391:                 // Security check
392:                 $depend = cSecurity::escapeString($tempXml->dependencies->depend[$i]);
393: 
394:                 // If is no dependencie name defined please go to next dependencie
395:                 if ($depend == "") {
396:                     continue;
397:                 }
398: 
399:                 // Build uuid variable from attributes
400:                 foreach ($tempXml->dependencies->depend[$i]->attributes() as $key => $value) {
401: 
402:                     // We use only uuid attribute and can ignore other attributes
403:                     if ($key  == "uuid") {
404:                         $uuidTemp = cSecurity::escapeString($value);
405:                     }
406:                 }
407: 
408:                 // Return false if uuid from plugin to uninstall and depended plugin is the same
409:                 // AND depended plugin is active
410:                 if ($uuidTemp === $uuidUninstall) {
411: 
412:                     $this->_PimPluginCollection->setWhere('uuid', $tempXml->general->uuid);
413:                     $this->_PimPluginCollection->setWhere('active', '1');
414:                     $this->_PimPluginCollection->query();
415: 
416:                     if ($this->_PimPluginCollection->count() != 0) {
417:                         self::setPluginName($tempXml->general->plugin_name);
418:                         return false;
419:                     }
420:                 }
421:             }
422:         }
423: 
424:         return true;
425:     }
426: 
427:     /**
428:      * Check file type, Plugin Manager accepts only Zip archives
429:      *
430:      * @throws cException
431:      */
432:     private function checkZip() {
433:         if (cString::getPartOfString($_FILES['package']['name'], -4) != ".zip") {
434:             self::error(i18n('Plugin Manager accepts only Zip archives', 'pim'));
435:         }
436:     }
437: 
438:     /**
439:      * Validate Xml source
440:      * @param string $xml
441:      * @return bool
442:      */
443:     private function validXml($xml) {
444: 
445:         // Initializing PHP DomDocument class
446:         $dom = new DomDocument();
447:         $dom->loadXML($xml);
448: 
449:         // Validate
450:         if ($dom->schemaValidate('plugins' . DIRECTORY_SEPARATOR . 'pim' . DIRECTORY_SEPARATOR . 'xml' . DIRECTORY_SEPARATOR . 'plugin_info.xsd')) {
451:             return true;
452:         } else {
453:             return false;
454:         }
455:     }
456: 
457:     /**
458:      * Error function with pim_error-Template
459:      *
460:      * @param string $message
461:      *
462:      * @throws cException
463:      * @throws cInvalidArgumentException
464:      */
465:     protected static function error($message = '') {
466: 
467:         // Get session variable
468:         $session = cRegistry::getSession();
469: 
470:         // Destroy temporary files if plugin is uploaded
471:         if (self::getMode() == 2) {
472:             self::$_PimPluginArchiveExtractor->destroyTempFiles();
473:         }
474: 
475:         // Error template
476:         $pimError = new cGuiPage('pim_error', 'pim');
477:         $pimError->set('s', 'BACKLINK', $session->url('main.php?area=pim&frame=4'));
478:         $pimError->set('s', 'LANG_BACKLINK', i18n('Back to Plugin Manager', 'pim'));
479:         $pimError->displayError($message);
480:         $pimError->render();
481:         exit();
482:     }
483: 
484:     /**
485:      * Info function, used displayOk CONTENIDO method
486:      *
487:      * @param string $message
488:      */
489:     protected static function info($message = '') {
490:         self::$_GuiPage->displayOk($message);
491:     }
492: 
493: }
494: 
CMS CONTENIDO 4.10.1 API documentation generated by ApiGen 2.8.0