Tho*_*sen 5 joomla command-line-interface joomla-extensions joomla2.5 joomla3.0
我正在尝试编写一个Joomla CLI脚本,自动将站点升级到当前版本.在Joomla中,这似乎是通过*com_joomlaupdate*完成的.我们的想法是能够从管理员前端升级服务器上的任何Joomla站点.
我编写了以下内容进行测试,尝试通过直接访问其模型中的方法来模拟com_joomlaupdate中的控制器.我不熟悉joomla框架所以我可能在这里做一些愚蠢的事情.
<?php
const _JEXEC = 1;
error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 1);
define('JPATH_BASE', dirname(__DIR__));
require_once JPATH_BASE . '/includes/defines.php';
require_once JPATH_BASE . '/includes/framework.php';
require_once JPATH_LIBRARIES . '/import.legacy.php';
require_once JPATH_LIBRARIES . '/cms.php';
// Load the configuration
require_once JPATH_CONFIGURATION . '/configuration.php';
define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR . '/components/com_joomlaupdate');
require_once JPATH_COMPONENT_ADMINISTRATOR . '/models/default.php';
class Upgradejoomla extends JApplicationCli
{
public function doExecute()
{
$app = JFactory::getApplication('administrator');
$app->initialise();
$app->input->set('method', 'direct');
$this->out('Fetching updates...');
$updater = JModelLegacy::getInstance('JoomlaupdateModelDefault');
$updater->refreshUpdates();
$updater->applyUpdateSite();
$basename = $updater->download();
$app->setUserState('com_joomlaupdate.file', $basename);
$updater->createRestorationFile($basename);
echo ($updater->finaliseUpgrade());
$updater->cleanUp();
}
}
JApplicationCli::getInstance('Upgradejoomla')->execute();
Run Code Online (Sandbox Code Playgroud)
download()工作正常,我得到最新的文件,并将其放在tmp目录中.createRestorationFile()似乎也工作,我在com_joomlaupdate目录中得到一个restoration.php文件.
问题似乎与finaliseUpgrade().它调用setupInstall()Installer,它试图查找清单文件.我错过了(除其他事项外)我认为这个文件(或更新的全部内容)在某处解压缩的步骤.问题是我找不到任何在com_joomlaupdate中执行此操作的代码?
我试图在/ tmp中手动解压缩更新文件.当我这样做,finaliseUpgrade()实际上返回true,但该网站仍然保持旧版本.
好吧,我想通了。
部分更新是使用restore.php(显然取自Akeeba 备份)进行的。Joomla 对restore.php 进行了2 个ajax 调用,第一个返回一个工厂对象,您必须将其传回。还有 AES CTR 加密需要担心。我所做的是使用curl 来模仿Joomla 的ajax 调用。
这是当前的代码。它可能需要进行大量清理(不要对 URL 进行硬编码、更多错误检查等),但它确实有效。
const _JEXEC = 1;
error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 1);
define('JPATH_BASE', dirname(__DIR__));
require_once JPATH_BASE . '/includes/defines.php';
require_once JPATH_BASE . '/includes/framework.php';
require_once JPATH_LIBRARIES . '/import.legacy.php';
require_once JPATH_LIBRARIES . '/cms.php';
// Load the configuration
require_once JPATH_CONFIGURATION . '/configuration.php';
define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR . '/components/com_joomlaupdate');
require_once JPATH_COMPONENT_ADMINISTRATOR . '/models/default.php';
// restore.php is loud, using ob_end_clean() to shut it up, we need it for decryption
ob_start();
require_once JPATH_COMPONENT_ADMINISTRATOR . '/restore.php';
ob_end_clean();
class Upgradejoomla extends JApplicationCli
{
// Used to talk to restore.php, since it only comunicates using Ajax.
public function curlCall($data) {
$url = 'http://localhost/administrator/components/com_joomlaupdate/restore.php';
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_POST, true);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
$ret = curl_exec ($ch);
return $ret;
}
// Decrypt the JSON return.php passes back to us, and make it a php array while we're at it.
public function deCrypt($str, $password) {
$result = AKEncryptionAES::AESDecryptCtr($str, $password, 128);
return json_decode($result, true);
}
public function doExecute() {
// Get a Joomla-instance so createResorationFile() doesn't complain too much.
$app = JFactory::getApplication('site');
$app->initialise();
// Make sure we're not in FTP mode
$app->input->set('method', 'direct');
// com_joomlaupdate's model
$updater = JModelLegacy::getInstance('JoomlaupdateModelDefault');
// Make sure we know what the latest version is
$updater->refreshUpdates();
$updater->applyUpdateSite();
// Let's see if we're already on the latest version, the model always returns a null-object if this is the case
$version_check = $updater->getUpdateInformation();
if (is_null($version_check['object'])) {
echo 'No new updates available' . "\n";
return 0;
}
$this->out('Fetching updates...');
// Grab the update (ends up in /tmp)
$basename = $updater->download();
// Create restoration.php (ends up in /com_joomlaupdate)
$updater->createRestorationFile($basename);
// Grab the password that was generated and placed in restoration.php so we can decrypt later
$password = $app->getUserState('com_joomlaupdate.password', null);
// Ask restore.php to start
$first_pass = array (
"task" => "startRestore",
);
$result = $this->curlCall($first_pass);
$result = $this->deCrypt($result, $password);
// Now we can pass back the factory-object we got and let restore.php do its thing
$second_pass = array (
"task" => "stepRestore",
"factory" => $result['factory']
);
$result = $this->curlCall($second_pass);
$result = $this->deCrypt($result, $password);
if ($result['done'] == 1) {
echo "Success!". "\n";
}
// Update SQL etc based on the manifest file we got with the update
$updater->finaliseUpgrade();
$updater->cleanUp();
}
}
JApplicationCli::getInstance('Upgradejoomla')->execute();
Run Code Online (Sandbox Code Playgroud)