Source for file module.php

Documentation is available at module.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Libraries
  4.  * @subpackage  Installer
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. jimport('joomla.base.adapterinstance');
  13. jimport('joomla.filesystem.folder');
  14.  
  15. /**
  16.  * Module installer
  17.  *
  18.  * @package     Joomla.Libraries
  19.  * @subpackage  Installer
  20.  * @since       3.1
  21.  */
  22. {
  23.     /**
  24.      * Install function routing
  25.      *
  26.      * @var    string 
  27.      * @since  3.1
  28.      */
  29.     protected $route = 'Install';
  30.  
  31.     /**
  32.      * The installation manifest XML object
  33.      *
  34.      * @var    SimpleXMLElement 
  35.      * @since  3.1
  36.      */
  37.     protected $manifest = null;
  38.  
  39.     /**
  40.      * A path to the PHP file that the scriptfile declaration in
  41.      * the manifest refers to.
  42.      *
  43.      * @var    string 
  44.      * @since  3.1
  45.      */
  46.     protected $manifest_script = null;
  47.  
  48.     /**
  49.      * Extension name
  50.      *
  51.      * @var    string 
  52.      * @since  3.1
  53.      */
  54.     protected $name = null;
  55.  
  56.     /**
  57.      * Extension element
  58.      *
  59.      * @var    string 
  60.      * @since  3.1
  61.      */
  62.     protected $element = null;
  63.  
  64.     /**
  65.      * <scriptfile> element of the extension manifest
  66.      *
  67.      * @var    object 
  68.      * @since  3.1
  69.      */
  70.     protected $scriptElement = null;
  71.  
  72.     /**
  73.      * Custom loadLanguage method
  74.      *
  75.      * @param   string  $path  The path where we find language files
  76.      *
  77.      * @return  void 
  78.      *
  79.      * @since   3.1
  80.      */
  81.     public function loadLanguage($path null)
  82.     {
  83.         $source $this->parent->getPath('source');
  84.  
  85.         if (!$source)
  86.         {
  87.             $this->parent
  88.                 ->setPath(
  89.                 'source',
  90.                 ($this->parent->extension->client_id JPATH_ADMINISTRATOR JPATH_SITE'/modules/' $this->parent->extension->element
  91.             );
  92.         }
  93.  
  94.         $this->manifest = $this->parent->getManifest();
  95.  
  96.         if ($this->manifest->files)
  97.         {
  98.             $element $this->manifest->files;
  99.             $extension '';
  100.  
  101.             if (count($element->children()))
  102.             {
  103.                 foreach ($element->children(as $file)
  104.                 {
  105.                     if ((string) $file->attributes()->module)
  106.                     {
  107.                         $extension strtolower((string) $file->attributes()->module);
  108.                         break;
  109.                     }
  110.                 }
  111.             }
  112.  
  113.             if ($extension)
  114.             {
  115.                 $lang JFactory::getLanguage();
  116.                 $source $path $path ($this->parent->extension->client_id JPATH_ADMINISTRATOR JPATH_SITE'/modules/' $extension;
  117.                 $folder = (string) $element->attributes()->folder;
  118.  
  119.                 if ($folder && file_exists($path '/' $folder))
  120.                 {
  121.                     $source $path '/' $folder;
  122.                 }
  123.  
  124.                 $client = (string) $this->manifest->attributes()->client;
  125.                 $lang->load($extension '.sys'$sourcenullfalsetrue)
  126.                     || $lang->load($extension '.sys'constant('JPATH_' strtoupper($client))nullfalsetrue);
  127.             }
  128.         }
  129.     }
  130.  
  131.     /**
  132.      * Custom install method
  133.      *
  134.      * @return  boolean  True on success
  135.      *
  136.      * @since   3.1
  137.      */
  138.     public function install()
  139.     {
  140.         // Get a database connector object
  141.         $db $this->parent->getDbo();
  142.  
  143.         // Get the extension manifest object
  144.         $this->manifest = $this->parent->getManifest();
  145.  
  146.         /*
  147.          * ---------------------------------------------------------------------------------------------
  148.          * Manifest Document Setup Section
  149.          * ---------------------------------------------------------------------------------------------
  150.          */
  151.  
  152.         // Set the extensions name
  153.         $name = (string) $this->manifest->name;
  154.         $name JFilterInput::getInstance()->clean($name'string');
  155.         $this->set('name'$name);
  156.  
  157.         // Get the module description
  158.         $description = (string) $this->manifest->description;
  159.  
  160.         if ($description)
  161.         {
  162.             $this->parent->set('message'JText::_($description));
  163.         }
  164.         else
  165.         {
  166.             $this->parent->set('message''');
  167.         }
  168.  
  169.         /*
  170.          * ---------------------------------------------------------------------------------------------
  171.          * Target Application Section
  172.          * ---------------------------------------------------------------------------------------------
  173.          */
  174.  
  175.         // Get the target application
  176.         if ($cname = (string) $this->manifest->attributes()->client)
  177.         {
  178.             // Attempt to map the client to a base path
  179.             $client JApplicationHelper::getClientInfo($cnametrue);
  180.  
  181.             if ($client === false)
  182.             {
  183.                 $this->parent
  184.                     ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_UNKNOWN_CLIENT'JText::_('JLIB_INSTALLER_' $this->route)$client->name));
  185.  
  186.                 return false;
  187.             }
  188.  
  189.             $basePath $client->path;
  190.             $clientId $client->id;
  191.         }
  192.         else
  193.         {
  194.             // No client attribute was found so we assume the site as the client
  195.             $basePath JPATH_SITE;
  196.             $clientId 0;
  197.         }
  198.  
  199.         // Set the installation path
  200.         $element '';
  201.  
  202.         if (count($this->manifest->files->children()))
  203.         {
  204.             foreach ($this->manifest->files->children(as $file)
  205.             {
  206.                 if ((string) $file->attributes()->module)
  207.                 {
  208.                     $element = (string) $file->attributes()->module;
  209.                     $this->set('element'$element);
  210.  
  211.                     break;
  212.                 }
  213.             }
  214.         }
  215.         if (!empty($element))
  216.         {
  217.             $this->parent->setPath('extension_root'$basePath '/modules/' $element);
  218.         }
  219.         else
  220.         {
  221.             $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_NOFILE'JText::_('JLIB_INSTALLER_' $this->route)));
  222.  
  223.             return false;
  224.         }
  225.  
  226.         /*
  227.          * Check to see if a module by the same name is already installed
  228.          * If it is, then update the table because if the files aren't there
  229.          * we can assume that it was (badly) uninstalled
  230.          * If it isn't, add an entry to extensions
  231.          */
  232.         $query $db->getQuery(true)
  233.             ->select($db->quoteName('extension_id'))
  234.             ->from($db->quoteName('#__extensions'))
  235.             ->where($db->quoteName('element'' = ' $db->quote($element))
  236.             ->where($db->quoteName('client_id'' = ' . (int) $clientId);
  237.         $db->setQuery($query);
  238.  
  239.         try
  240.         {
  241.             $db->execute();
  242.         }
  243.         catch (RuntimeException $e)
  244.         {
  245.             // Install failed, roll back changes
  246.             $this->parent
  247.                 ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK'JText::_('JLIB_INSTALLER_' $this->route)$db->stderr(true)));
  248.  
  249.             return false;
  250.         }
  251.  
  252.         $id $db->loadResult();
  253.  
  254.         /*
  255.          * If the module directory already exists, then we will assume that the
  256.          * module is already installed or another module is using that
  257.          * directory.
  258.          * Check that this is either an issue where its not overwriting or it is
  259.          * set to upgrade anyway
  260.          */
  261.  
  262.         if (file_exists($this->parent->getPath('extension_root')) && (!$this->parent->isOverwrite(|| $this->parent->isUpgrade()))
  263.         {
  264.             // Look for an update function or update tag
  265.             $updateElement $this->manifest->update;
  266.  
  267.             // Upgrade manually set or update function available or update tag detected
  268.             if ($this->parent->isUpgrade(|| ($this->parent->manifestClass && method_exists($this->parent->manifestClass'update'))
  269.                 || $updateElement)
  270.             {
  271.                 // Force this one
  272.                 $this->parent->setOverwrite(true);
  273.                 $this->parent->setUpgrade(true);
  274.  
  275.                 if ($id)
  276.                 {
  277.                     // If there is a matching extension mark this as an update; semantics really
  278.                     $this->route = 'Update';
  279.                 }
  280.             }
  281.             elseif (!$this->parent->isOverwrite())
  282.             {
  283.                 // Overwrite is set
  284.                 // We didn't have overwrite set, find an update function or find an update tag so lets call it safe
  285.                 $this->parent
  286.                     ->abort(
  287.                     JText::sprintf(
  288.                         'JLIB_INSTALLER_ABORT_MOD_INSTALL_DIRECTORY'JText::_('JLIB_INSTALLER_' $this->route),
  289.                         $this->parent->getPath('extension_root')
  290.                     )
  291.                 );
  292.  
  293.                 return false;
  294.             }
  295.         }
  296.  
  297.         /*
  298.          * ---------------------------------------------------------------------------------------------
  299.          * Installer Trigger Loading
  300.          * ---------------------------------------------------------------------------------------------
  301.          */
  302.  
  303.         // If there is an manifest class file, let's load it; we'll copy it later (don't have destination yet)
  304.         $this->scriptElement = $this->manifest->scriptfile;
  305.         $manifestScript = (string) $this->manifest->scriptfile;
  306.  
  307.         if ($manifestScript)
  308.         {
  309.             $manifestScriptFile $this->parent->getPath('source''/' $manifestScript;
  310.  
  311.             if (is_file($manifestScriptFile))
  312.             {
  313.                 // Load the file
  314.                 include_once $manifestScriptFile;
  315.             }
  316.  
  317.             // Set the class name
  318.             $classname $element 'InstallerScript';
  319.  
  320.             if (class_exists($classname))
  321.             {
  322.                 // Create a new instance.
  323.                 $this->parent->manifestClass new $classname($this);
  324.  
  325.                 // And set this so we can copy it later.
  326.                 $this->set('manifest_script'$manifestScript);
  327.             }
  328.         }
  329.  
  330.         // Run preflight if possible (since we know we're not an update)
  331.         ob_start();
  332.         ob_implicit_flush(false);
  333.  
  334.         if ($this->parent->manifestClass && method_exists($this->parent->manifestClass'preflight'))
  335.         {
  336.             if ($this->parent->manifestClass->preflight($this->route$this=== false)
  337.             {
  338.                 // Preflight failed, rollback changes
  339.                 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_CUSTOM_INSTALL_FAILURE'));
  340.  
  341.                 return false;
  342.             }
  343.         }
  344.  
  345.         // Create msg object; first use here
  346.         $msg ob_get_contents();
  347.         ob_end_clean();
  348.  
  349.         /*
  350.          * ---------------------------------------------------------------------------------------------
  351.          * Filesystem Processing Section
  352.          * ---------------------------------------------------------------------------------------------
  353.          */
  354.  
  355.         // If the module directory does not exist, lets create it
  356.         $created false;
  357.  
  358.         if (!file_exists($this->parent->getPath('extension_root')))
  359.         {
  360.             if (!$created JFolder::create($this->parent->getPath('extension_root')))
  361.             {
  362.                 $this->parent
  363.                     ->abort(
  364.                     JText::sprintf(
  365.                         'JLIB_INSTALLER_ABORT_MOD_INSTALL_CREATE_DIRECTORY'JText::_('JLIB_INSTALLER_' $this->route),
  366.                         $this->parent->getPath('extension_root')
  367.                     )
  368.                 );
  369.  
  370.                 return false;
  371.             }
  372.         }
  373.  
  374.         /*
  375.          * Since we created the module directory and will want to remove it if
  376.          * we have to roll back the installation, let's add it to the
  377.          * installation step stack
  378.          */
  379.  
  380.         if ($created)
  381.         {
  382.             $this->parent->pushStep(array('type' => 'folder''path' => $this->parent->getPath('extension_root')));
  383.         }
  384.  
  385.         // Copy all necessary files
  386.         if ($this->parent->parseFiles($this->manifest->files-1=== false)
  387.         {
  388.             // Install failed, roll back changes
  389.             $this->parent->abort();
  390.  
  391.             return false;
  392.         }
  393.  
  394.         // If there is a manifest script, let's copy it.
  395.         if ($this->get('manifest_script'))
  396.         {
  397.             $path['src'$this->parent->getPath('source''/' $this->get('manifest_script');
  398.             $path['dest'$this->parent->getPath('extension_root''/' $this->get('manifest_script');
  399.  
  400.             if (!file_exists($path['dest']|| $this->parent->isOverwrite())
  401.             {
  402.                 if (!$this->parent->copyFiles(array($path)))
  403.                 {
  404.                     // Install failed, rollback changes
  405.                     $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_MANIFEST'));
  406.  
  407.                     return false;
  408.                 }
  409.             }
  410.         }
  411.  
  412.         // Parse optional tags
  413.         $this->parent->parseMedia($this->manifest->media$clientId);
  414.         $this->parent->parseLanguages($this->manifest->languages$clientId);
  415.  
  416.         /*
  417.          * ---------------------------------------------------------------------------------------------
  418.          * Database Processing Section
  419.          * ---------------------------------------------------------------------------------------------
  420.          */
  421.  
  422.         $row JTable::getInstance('extension');
  423.  
  424.         // Was there a module already installed with the same name?
  425.         if ($id)
  426.         {
  427.             // Load the entry and update the manifest_cache
  428.             $row->load($id);
  429.  
  430.             // Update name
  431.             $row->name $this->get('name');
  432.  
  433.             // Update manifest
  434.             $row->manifest_cache $this->parent->generateManifestCache();
  435.  
  436.             if (!$row->store())
  437.             {
  438.                 // Install failed, roll back changes
  439.                 $this->parent
  440.                     ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK'JText::_('JLIB_INSTALLER_' $this->route)$db->stderr(true)));
  441.  
  442.                 return false;
  443.             }
  444.         }
  445.         else
  446.         {
  447.             $row->set('name'$this->get('name'));
  448.             $row->set('type''module');
  449.             $row->set('element'$this->get('element'));
  450.  
  451.             // There is no folder for modules
  452.             $row->set('folder''');
  453.             $row->set('enabled'1);
  454.             $row->set('protected'0);
  455.             $row->set('access'$clientId == 0);
  456.             $row->set('client_id'$clientId);
  457.             $row->set('params'$this->parent->getParams());
  458.  
  459.             // Custom data
  460.             $row->set('custom_data''');
  461.             $row->set('manifest_cache'$this->parent->generateManifestCache());
  462.  
  463.             if (!$row->store())
  464.             {
  465.                 // Install failed, roll back changes
  466.                 $this->parent
  467.                     ->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_ROLLBACK'JText::_('JLIB_INSTALLER_' $this->route)$db->stderr(true)));
  468.  
  469.                 return false;
  470.             }
  471.  
  472.             // Since we have created a module item, we add it to the installation step stack
  473.             // so that if we have to rollback the changes we can undo it.
  474.             $this->parent->pushStep(array('type' => 'extension''extension_id' => $row->extension_id));
  475.  
  476.             // Create unpublished module in jos_modules
  477.             $name preg_replace('#[\*?]#'''JText::_($this->get('name')));
  478.             $module JTable::getInstance('module');
  479.             $module->set('title'$name);
  480.             $module->set('content''');
  481.             $module->set('module'$this->get('element'));
  482.             $module->set('access''1');
  483.             $module->set('showtitle''1');
  484.             $module->set('params''');
  485.             $module->set('client_id'$clientId);
  486.             $module->set('language''*');
  487.  
  488.             $module->store();
  489.         }
  490.  
  491.         // Let's run the queries for the module
  492.         if (strtolower($this->route== 'install')
  493.         {
  494.             $result $this->parent->parseSQLFiles($this->manifest->install->sql);
  495.  
  496.             if ($result === false)
  497.             {
  498.                 // Install failed, rollback changes
  499.                 $this->parent
  500.                     ->abort(
  501.                     JText::sprintf('JLIB_INSTALLER_ABORT_MOD_INSTALL_SQL_ERROR'JText::_('JLIB_INSTALLER_' $this->route)$db->stderr(true))
  502.                 );
  503.  
  504.                 return false;
  505.             }
  506.  
  507.             // Set the schema version to be the latest update version
  508.             if ($this->manifest->update)
  509.             {
  510.                 $this->parent->setSchemaVersion($this->manifest->update->schemas$row->extension_id);
  511.             }
  512.         }
  513.         elseif (strtolower($this->route== 'update')
  514.         {
  515.             if ($this->manifest->update)
  516.             {
  517.                 $result $this->parent->parseSchemaUpdates($this->manifest->update->schemas$row->extension_id);
  518.  
  519.                 if ($result === false)
  520.                 {
  521.                     // Install failed, rollback changes
  522.                     $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ABORT_MOD_UPDATE_SQL_ERROR'$db->stderr(true)));
  523.  
  524.                     return false;
  525.                 }
  526.             }
  527.         }
  528.  
  529.         // Run the custom method based on the route
  530.         ob_start();
  531.         ob_implicit_flush(false);
  532.  
  533.         if ($this->parent->manifestClass && method_exists($this->parent->manifestClass$this->route))
  534.         {
  535.             if ($this->parent->manifestClass->{$this->route}($this=== false)
  536.             {
  537.                 // Install failed, rollback changes
  538.                 $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_CUSTOM_INSTALL_FAILURE'));
  539.  
  540.                 return false;
  541.             }
  542.         }
  543.  
  544.         // Append messages
  545.         $msg .= ob_get_contents();
  546.         ob_end_clean();
  547.  
  548.         /**
  549.          * ---------------------------------------------------------------------------------------------
  550.          * Finalization and Cleanup Section
  551.          * ---------------------------------------------------------------------------------------------
  552.          */
  553.  
  554.         // Lastly, we will copy the manifest file to its appropriate place.
  555.         if (!$this->parent->copyManifest(-1))
  556.         {
  557.             // Install failed, rollback changes
  558.             $this->parent->abort(JText::_('JLIB_INSTALLER_ABORT_MOD_INSTALL_COPY_SETUP'));
  559.  
  560.             return false;
  561.         }
  562.  
  563.         // And now we run the postflight
  564.         ob_start();
  565.         ob_implicit_flush(false);
  566.  
  567.         if ($this->parent->manifestClass && method_exists($this->parent->manifestClass'postflight'))
  568.         {
  569.             $this->parent->manifestClass->postflight($this->route$this);
  570.         }
  571.  
  572.         // Append messages
  573.         $msg .= ob_get_contents();
  574.         ob_end_clean();
  575.  
  576.         if ($msg != '')
  577.         {
  578.             $this->parent->set('extension_message'$msg);
  579.         }
  580.  
  581.         return $row->get('extension_id');
  582.     }
  583.  
  584.     /**
  585.      * Custom update method
  586.      *
  587.      * This is really a shell for the install system
  588.      *
  589.      * @return  boolean  True on success.
  590.      *
  591.      * @since   3.1
  592.      */
  593.     public function update()
  594.     {
  595.         // Set the overwrite setting
  596.         $this->parent->setOverwrite(true);
  597.         $this->parent->setUpgrade(true);
  598.  
  599.         // Set the route for the install
  600.         $this->route = 'update';
  601.  
  602.         // Go to install which handles updates properly
  603.         return $this->install();
  604.     }
  605.  
  606.     /**
  607.      * Custom discover method
  608.      *
  609.      * @return  array  JExtension list of extensions available
  610.      *
  611.      * @since   3.1
  612.      */
  613.     public function discover()
  614.     {
  615.         $results array();
  616.         $site_list JFolder::folders(JPATH_SITE '/modules');
  617.         $admin_list JFolder::folders(JPATH_ADMINISTRATOR '/modules');
  618.         $site_info JApplicationHelper::getClientInfo('site'true);
  619.         $admin_info JApplicationHelper::getClientInfo('administrator'true);
  620.  
  621.         foreach ($site_list as $module)
  622.         {
  623.             $manifest_details JInstaller::parseXMLInstallFile(JPATH_SITE "/modules/$module/$module.xml");
  624.             $extension JTable::getInstance('extension');
  625.             $extension->set('type''module');
  626.             $extension->set('client_id'$site_info->id);
  627.             $extension->set('element'$module);
  628.             $extension->set('folder''');
  629.             $extension->set('name'$module);
  630.             $extension->set('state'-1);
  631.             $extension->set('manifest_cache'json_encode($manifest_details));
  632.             $extension->set('params''{}');
  633.             $results[clone $extension;
  634.         }
  635.  
  636.         foreach ($admin_list as $module)
  637.         {
  638.             $manifest_details JInstaller::parseXMLInstallFile(JPATH_ADMINISTRATOR "/modules/$module/$module.xml");
  639.             $extension JTable::getInstance('extension');
  640.             $extension->set('type''module');
  641.             $extension->set('client_id'$admin_info->id);
  642.             $extension->set('element'$module);
  643.             $extension->set('folder''');
  644.             $extension->set('name'$module);
  645.             $extension->set('state'-1);
  646.             $extension->set('manifest_cache'json_encode($manifest_details));
  647.             $extension->set('params''{}');
  648.             $results[clone $extension;
  649.         }
  650.  
  651.         return $results;
  652.     }
  653.  
  654.     /**
  655.      * Custom discover_install method
  656.      *
  657.      * @return  mixed  Extension ID on success, boolean false on failure
  658.      *
  659.      * @since   3.1
  660.      */
  661.     public function discover_install()
  662.     {
  663.         // Modules are like templates, and are one of the easiest
  664.         // If its not in the extensions table we just add it
  665.         $client JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  666.         $manifestPath $client->path '/modules/' $this->parent->extension->element '/' $this->parent->extension->element '.xml';
  667.         $this->parent->manifest $this->parent->isManifest($manifestPath);
  668.         $description = (string) $this->parent->manifest->description;
  669.  
  670.         if ($description)
  671.         {
  672.             $this->parent->set('message'JText::_($description));
  673.         }
  674.         else
  675.         {
  676.             $this->parent->set('message''');
  677.         }
  678.  
  679.         $this->parent->setPath('manifest'$manifestPath);
  680.         $manifest_details JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
  681.  
  682.         // TODO: Re-evaluate this; should we run installation triggers? postflight perhaps?
  683.         $this->parent->extension->manifest_cache json_encode($manifest_details);
  684.         $this->parent->extension->state 0;
  685.         $this->parent->extension->name $manifest_details['name'];
  686.         $this->parent->extension->enabled 1;
  687.         $this->parent->extension->params $this->parent->getParams();
  688.  
  689.         if ($this->parent->extension->store())
  690.         {
  691.             return $this->parent->extension->get('extension_id');
  692.         }
  693.         else
  694.         {
  695.             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_DISCOVER_STORE_DETAILS')JLog::WARNING'jerror');
  696.  
  697.             return false;
  698.         }
  699.     }
  700.  
  701.     /**
  702.      * Refreshes the extension table cache
  703.      *
  704.      * @return  boolean  Result of operation, true if updated, false on failure.
  705.      *
  706.      * @since   3.1
  707.      */
  708.     public function refreshManifestCache()
  709.     {
  710.         $client JApplicationHelper::getClientInfo($this->parent->extension->client_id);
  711.         $manifestPath $client->path '/modules/' $this->parent->extension->element '/' $this->parent->extension->element '.xml';
  712.         $this->parent->manifest $this->parent->isManifest($manifestPath);
  713.         $this->parent->setPath('manifest'$manifestPath);
  714.         $manifest_details JInstaller::parseXMLInstallFile($this->parent->getPath('manifest'));
  715.         $this->parent->extension->manifest_cache json_encode($manifest_details);
  716.         $this->parent->extension->name $manifest_details['name'];
  717.  
  718.         if ($this->parent->extension->store())
  719.         {
  720.             return true;
  721.         }
  722.         else
  723.         {
  724.             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_REFRESH_MANIFEST_CACHE')JLog::WARNING'jerror');
  725.  
  726.             return false;
  727.         }
  728.     }
  729.  
  730.     /**
  731.      * Custom uninstall method
  732.      *
  733.      * @param   integer  $id  The id of the module to uninstall
  734.      *
  735.      * @return  boolean  True on success
  736.      *
  737.      * @since   3.1
  738.      */
  739.     public function uninstall($id)
  740.     {
  741.         $row null;
  742.         $retval true;
  743.         $db $this->parent->getDbo();
  744.  
  745.         // First order of business will be to load the module object table from the database.
  746.         // This should give us the necessary information to proceed.
  747.         $row JTable::getInstance('extension');
  748.  
  749.         if (!$row->load((int) $id|| !strlen($row->element))
  750.         {
  751.             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_ERRORUNKOWNEXTENSION')JLog::WARNING'jerror');
  752.  
  753.             return false;
  754.         }
  755.  
  756.         // Is the module we are trying to uninstall a core one?
  757.         // Because that is not a good idea...
  758.         if ($row->protected)
  759.         {
  760.             JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_WARNCOREMODULE'$row->name)JLog::WARNING'jerror');
  761.  
  762.             return false;
  763.         }
  764.  
  765.         // Get the extension root path
  766.         $element $row->element;
  767.         $client JApplicationHelper::getClientInfo($row->client_id);
  768.  
  769.         if ($client === false)
  770.         {
  771.             $this->parent->abort(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_UNKNOWN_CLIENT'$row->client_id));
  772.  
  773.             return false;
  774.         }
  775.         $this->parent->setPath('extension_root'$client->path '/modules/' $element);
  776.  
  777.         $this->parent->setPath('source'$this->parent->getPath('extension_root'));
  778.  
  779.         // Get the module's manifest objecct
  780.         // We do findManifest to avoid problem when uninstalling a list of extensions: getManifest cache its manifest file.
  781.         $this->parent->findManifest();
  782.         $this->manifest = $this->parent->getManifest();
  783.  
  784.         // Attempt to load the language file; might have uninstall strings
  785.         $this->loadLanguage(($row->client_id JPATH_ADMINISTRATOR JPATH_SITE'/modules/' $element);
  786.  
  787.         // If there is an manifest class file, let's load it
  788.         $this->scriptElement = $this->manifest->scriptfile;
  789.         $manifestScript = (string) $this->manifest->scriptfile;
  790.  
  791.         if ($manifestScript)
  792.         {
  793.             $manifestScriptFile $this->parent->getPath('extension_root''/' $manifestScript;
  794.  
  795.             if (is_file($manifestScriptFile))
  796.             {
  797.                 // Load the file
  798.                 include_once $manifestScriptFile;
  799.             }
  800.  
  801.             // Set the class name
  802.             $classname $element 'InstallerScript';
  803.  
  804.             if (class_exists($classname))
  805.             {
  806.                 // Create a new instance
  807.                 $this->parent->manifestClass new $classname($this);
  808.  
  809.                 // And set this so we can copy it later
  810.                 $this->set('manifest_script'$manifestScript);
  811.             }
  812.         }
  813.  
  814.         ob_start();
  815.         ob_implicit_flush(false);
  816.  
  817.         // Run uninstall if possible
  818.         if ($this->parent->manifestClass && method_exists($this->parent->manifestClass'uninstall'))
  819.         {
  820.             $this->parent->manifestClass->uninstall($this);
  821.         }
  822.  
  823.         $msg ob_get_contents();
  824.         ob_end_clean();
  825.  
  826.         if ($msg != '')
  827.         {
  828.             $this->parent->set('extension_message'$msg);
  829.         }
  830.  
  831.         if (!($this->manifest instanceof SimpleXMLElement))
  832.         {
  833.             // Make sure we delete the folders
  834.             JFolder::delete($this->parent->getPath('extension_root'));
  835.             JLog::add(JText::_('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_INVALID_NOTFOUND_MANIFEST')JLog::WARNING'jerror');
  836.  
  837.             return false;
  838.         }
  839.  
  840.         // Let's run the uninstall queries for the module
  841.         $result $this->parent->parseSQLFiles($this->manifest->uninstall->sql);
  842.  
  843.         if ($result === false)
  844.         {
  845.             // Install failed, rollback changes
  846.             JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_SQL_ERROR'$db->stderr(true))JLog::WARNING'jerror');
  847.             $retval false;
  848.         }
  849.  
  850.         // Remove the schema version
  851.         $query $db->getQuery(true)
  852.             ->delete('#__schemas')
  853.             ->where('extension_id = ' $row->extension_id);
  854.         $db->setQuery($query);
  855.         $db->execute();
  856.  
  857.         // Remove other files
  858.         $this->parent->removeFiles($this->manifest->media);
  859.         $this->parent->removeFiles($this->manifest->languages$row->client_id);
  860.  
  861.         // Let's delete all the module copies for the type we are uninstalling
  862.         $query->clear()
  863.             ->select($db->quoteName('id'))
  864.             ->from($db->quoteName('#__modules'))
  865.             ->where($db->quoteName('module'' = ' $db->quote($row->element))
  866.             ->where($db->quoteName('client_id'' = ' . (int) $row->client_id);
  867.         $db->setQuery($query);
  868.  
  869.         try
  870.         {
  871.             $modules $db->loadColumn();
  872.         }
  873.         catch (RuntimeException $e)
  874.         {
  875.             $modules array();
  876.         }
  877.  
  878.         // Do we have any module copies?
  879.         if (count($modules))
  880.         {
  881.             // Ensure the list is sane
  882.             JArrayHelper::toInteger($modules);
  883.             $modID implode(','$modules);
  884.  
  885.             // Wipe out any items assigned to menus
  886.             $query 'DELETE FROM #__modules_menu WHERE moduleid IN (' $modID ')';
  887.             $db->setQuery($query);
  888.  
  889.             try
  890.             {
  891.                 $db->execute();
  892.             }
  893.             catch (RuntimeException $e)
  894.             {
  895.                 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION'$db->stderr(true))JLog::WARNING'jerror');
  896.                 $retval false;
  897.             }
  898.  
  899.             // Wipe out any instances in the modules table
  900.             $query 'DELETE FROM #__modules WHERE id IN (' $modID ')';
  901.             $db->setQuery($query);
  902.  
  903.             try
  904.             {
  905.                 $db->execute();
  906.             }
  907.             catch (RuntimeException $e)
  908.             {
  909.                 JLog::add(JText::sprintf('JLIB_INSTALLER_ERROR_MOD_UNINSTALL_EXCEPTION'$db->stderr(true))JLog::WARNING'jerror');
  910.                 $retval false;
  911.             }
  912.         }
  913.  
  914.         // Now we will no longer need the module object, so let's delete it and free up memory
  915.         $row->delete($row->extension_id);
  916.         $query 'DELETE FROM #__modules WHERE module = ' $db->quote($row->element' AND client_id = ' $row->client_id;
  917.         $db->setQuery($query);
  918.  
  919.         try
  920.         {
  921.             // Clean up any other ones that might exist as well
  922.             $db->execute();
  923.         }
  924.         catch (RuntimeException $e)
  925.         {
  926.             // Ignore the error...
  927.         }
  928.  
  929.         unset($row);
  930.  
  931.         // Remove the installation folder
  932.         if (!JFolder::delete($this->parent->getPath('extension_root')))
  933.         {
  934.             // JFolder should raise an error
  935.             $retval false;
  936.         }
  937.  
  938.         return $retval;
  939.     }
  940.  
  941.     /**
  942.      * Custom rollback method
  943.      * - Roll back the menu item
  944.      *
  945.      * @param   array  $arg  Installation step to rollback
  946.      *
  947.      * @return  boolean  True on success
  948.      *
  949.      * @since   3.1
  950.      */
  951.     protected function _rollback_menu($arg)
  952.     {
  953.         // Get database connector object
  954.         $db $this->parent->getDbo();
  955.  
  956.         // Remove the entry from the #__modules_menu table
  957.         $query 'DELETE FROM #__modules_menu WHERE moduleid=' . (int) $arg['id'];
  958.         $db->setQuery($query);
  959.  
  960.         try
  961.         {
  962.             return $db->execute();
  963.         }
  964.         catch (RuntimeException $e)
  965.         {
  966.             return false;
  967.         }
  968.     }
  969.  
  970.     /**
  971.      * Custom rollback method
  972.      * - Roll back the module item
  973.      *
  974.      * @param   array  $arg  Installation step to rollback
  975.      *
  976.      * @return  boolean  True on success
  977.      *
  978.      * @since   3.1
  979.      */
  980.     protected function _rollback_module($arg)
  981.     {
  982.         // Get database connector object
  983.         $db $this->parent->getDbo();
  984.  
  985.         // Remove the entry from the #__modules table
  986.         $query 'DELETE FROM #__modules WHERE id=' . (int) $arg['id'];
  987.         $db->setQuery($query);
  988.  
  989.         try
  990.         {
  991.             return $db->execute();
  992.         }
  993.         catch (RuntimeException $e)
  994.         {
  995.             return false;
  996.         }
  997.     }
  998. }
  999.  
  1000. /**
  1001.  * Deprecated class placeholder. You should use JInstallerAdapterModule instead.
  1002.  *
  1003.  * @package     Joomla.Libraries
  1004.  * @subpackage  Installer
  1005.  * @since       3.1
  1006.  * @deprecated  4.0
  1007.  * @codeCoverageIgnore
  1008.  */
  1009. {
  1010. }

Documentation generated on Tue, 19 Nov 2013 15:08:42 +0100 by phpDocumentor 1.4.3