Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
0e12918
Add Import-Export to System-Information-Database
twister65 Aug 16, 2019
a85aea1
Fix integrity of the zip file to import
twister65 Sep 9, 2019
d44293c
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Sep 10, 2019
e6b7470
Delete temporary files.
twister65 Sep 10, 2019
43d015f
Tabs and spaces...
twister65 Sep 10, 2019
edd7d3a
JPATH_ROOT is already defined.
twister65 Sep 11, 2019
7b7132b
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Sep 12, 2019
5cb9f08
Merge branch '4.0-dev' into 4.0-dbdump
twister65 Sep 22, 2019
ea0ba05
Merge branch '4.0-dev' into 4.0-dbdump
twister65 Oct 19, 2019
a089867
Improved security
twister65 Oct 26, 2019
a659a52
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Oct 26, 2019
3bfd651
Merge branch '4.0-dbdump' of https://github.com/twister65/joomla-cms …
twister65 Oct 26, 2019
7192020
Fix merge conflict
twister65 Oct 26, 2019
607e95f
Merge branch '4.0-dev' into 4.0-dbdump
twister65 Oct 27, 2019
0ae368d
Merge branch '4.0-dev' into 4.0-dbdump
twister65 Oct 27, 2019
b03b57f
Update DatabaseController
twister65 Oct 29, 2019
92d6883
Export tables with the appropriate prefix.
twister65 Oct 30, 2019
4651411
Use strpos to find the table prefix
twister65 Nov 5, 2019
1d3b69b
Use $this->input
twister65 Nov 5, 2019
c2768ed
Update DatabaseController.php
twister65 Nov 5, 2019
947598c
Update administrator/components/com_installer/Model/DatabaseModel.php
twister65 Nov 5, 2019
1791e32
Use Joomla tmp path.
twister65 Nov 5, 2019
0dc04c2
Add param (doc) to import function
twister65 Nov 6, 2019
2ef094f
Merge branch '4.0-dev' into 4.0-dbdump
twister65 Nov 6, 2019
4a0941b
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Dec 15, 2019
a0cca4d
Add RawView to download the database snapshot.
twister65 Dec 25, 2019
7d156a2
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Dec 25, 2019
4e66779
Fix phpcs error.
twister65 Dec 25, 2019
2e46665
Fix phpcs error (next try).
twister65 Dec 25, 2019
bfbf948
Fix phpcs error (third try).
twister65 Dec 25, 2019
4aeec7e
Flush system output buffer
twister65 Dec 26, 2019
e409325
Use language strings for import messages.
twister65 Dec 27, 2019
87f8a33
Include the site name in the export file name.
twister65 Dec 28, 2019
a8a0e93
Process site name to have a safe file name.
twister65 Dec 28, 2019
7c1a596
Integrates the import button in the import box.
twister65 Jan 1, 2020
b897158
Checks if the zip file contains database export files.
twister65 Jan 4, 2020
ad03854
Fix phpcs error.
twister65 Jan 4, 2020
92768f9
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Jan 4, 2020
ee34bb0
Add zip filtering to the input file.
twister65 Jan 4, 2020
f5d88b5
Update administrator/components/com_installer/Model/DatabaseModel.php
twister65 Jan 5, 2020
56ecf71
Handles the exception to validate the ZIP file.
twister65 Jan 5, 2020
2336486
Use tabs to import or check the structure of the database.
twister65 Jan 11, 2020
00d9534
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Jan 11, 2020
e912e7d
Specify the title of the message.
twister65 Jan 12, 2020
4dc76b3
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Jan 12, 2020
552e060
Check the file size after selecting a file to upload.
twister65 Jan 19, 2020
3a30a7f
Use language string for the invalid feedback.
twister65 Jan 19, 2020
1ff18b2
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Jan 19, 2020
b811a2d
Disable/Enable the Import button depending on the file size.
twister65 Jan 19, 2020
fdd0946
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Feb 19, 2020
7310a23
Resolve conflict
twister65 Feb 19, 2020
524d259
Move RawView
twister65 Feb 19, 2020
83abd0e
Update fontawesome4 to fontawesome5 class
twister65 Feb 23, 2020
962ff50
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Mar 8, 2020
3420fd8
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Jul 12, 2020
6672121
Merge branch '4.0-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Aug 4, 2020
848d98d
Merge branch '4.1-dev' of https://github.com/joomla/joomla-cms into 4…
twister65 Aug 8, 2020
48f46d6
Apply suggestions from code review
twister65 Aug 21, 2021
33e1a5e
Update default_update.php
twister65 Aug 21, 2021
dc0a2bf
Merge branch '4.1-dev' into 4.0-dbdump
twister65 Aug 21, 2021
2769aca
Update default_import.php
twister65 Aug 21, 2021
30e08be
Merge branch '4.1-dev' into 4.0-dbdump
twister65 Oct 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class DatabaseController extends BaseController
*/
public function fix()
{
// Specify the title of the message
$title = sprintf('[%s]', Text::sprintf('COM_INSTALLER_VIEW_DEFAULT_TAB_FIX'));

// Check for request forgeries.
$this->checkToken();

Expand All @@ -44,6 +47,7 @@ public function fix()

if (!is_array($cid) || count($cid) < 1)
{
$this->app->getLogger()->warning($title, array('category' => 'jerror'));
$this->app->getLogger()->warning(
Text::_(
'COM_INSTALLER_ERROR_NO_EXTENSIONS_SELECTED'
Expand All @@ -68,6 +72,77 @@ public function fix()
$this->setRedirect(Route::_('index.php?option=com_installer&view=database', false));
}

/**
* Export all the database via XML
*
* @return void
*
* @since __DEPLOY_VERSION__
*/
public function export()
{
if ($view = $this->getView('Database', 'raw'))
{
/** @var DatabaseModel $model */
$model = $this->getModel('Database');

if ($model->export())
{
// Push the model into the view (as default).
$view->setModel($model, true);

// Push document object into the view.
$view->document = $this->app->getDocument();

$view->display();
}
}
}

/**
* Import all the database via XML
*
* @return void
*
* @since __DEPLOY_VERSION__
*/
public function import()
{
// Specify the title of the message
$title = sprintf('[%s]', Text::sprintf('COM_INSTALLER_VIEW_DEFAULT_TAB_IMPORT'));

// Get file to import in the database.
$file = $this->input->files->get('zip_file', null, 'raw');

if ($file['name'] == '')
{
$this->app->getLogger()->warning($title, ['category' => 'jerror']);
$this->app->getLogger()->warning(
Text::_(
'COM_INSTALLER_MSG_INSTALL_NO_FILE_SELECTED'
), ['category' => 'jerror']
);
}
else
{
/** @var DatabaseModel $model */
$model = $this->getModel('Database');

if ($model->import($file))
{
$this->app->enqueueMessage($title, 'message');
$this->setMessage(Text::_('COM_INSTALLER_MSG_DATABASE_IMPORT_OK'));
}
else
{
$this->app->enqueueMessage($title, 'error');
$this->setMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_ERROR', $file['name']), 'error');
}
}

$this->setRedirect(Route::_('index.php?option=com_installer&view=database', false));
}

/**
* Provide the data for a badge in a menu item via JSON
*
Expand Down
234 changes: 234 additions & 0 deletions administrator/components/com_installer/src/Model/DatabaseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

\defined('_JEXEC') or die;

use Joomla\Archive\Archive;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\Schema\ChangeSet;
Expand All @@ -20,7 +23,11 @@
use Joomla\Component\Installer\Administrator\Helper\InstallerHelper;
use Joomla\Database\DatabaseQuery;
use Joomla\Database\Exception\ExecutionFailureException;
use Joomla\Database\Exception\UnsupportedAdapterException;
use Joomla\Database\ParameterType;
use Joomla\Filesystem\Exception\FilesystemException;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\Registry\Registry;

\JLoader::register('JoomlaInstallerScript', JPATH_ADMINISTRATOR . '/components/com_admin/script.php');
Expand Down Expand Up @@ -337,6 +344,233 @@ public function fix($cids = array())
}
}

/**
* Get the filename of the temporary database archive
*
* @return string
*
* @since __DEPLOY_VERSION__
*/
public function getZipFilename()
{
return Factory::getApplication()->get('tmp_path') . '/joomla_db.zip';
}

/**
* Export all the database via XML
*
* @return boolean
*
* @since __DEPLOY_VERSION__
*/
public function export()
{
$db = $this->getDbo();

// Make sure the database supports exports before we get going
try
{
$exporter = $db->getExporter()->withStructure();
}
catch (UnsupportedAdapterException $e)
{
return false;
}

$tables = $db->getTableList();
$prefix = $db->getPrefix();

$zipFile = $this->getZipFilename();
$zipArchive = (new Archive)->getAdapter('zip');

foreach ($tables as $table)
{
if (strpos($table, $prefix) === 0)
{
$data = (string) $exporter->from($table)->withData(true);
$zipFilesArray[] = ['name' => $table . '.xml', 'data' => $data];
$zipArchive->create($zipFile, $zipFilesArray);
}
}

return true;
}

/**
* Checks if the zip file contains database export files
*
* @param string $file A zip archive to analyze
*
* @return void
*
* @since __DEPLOY_VERSION__
* @throws \RuntimeException
*/
private function checkZipFile($archive)
{
$db = $this->getDbo();
$zip = zip_open($archive);

if (!\is_resource($zip))
{
throw new \RuntimeException('Unable to open archive');
}

while ($file = @zip_read($zip))
{
if (strpos(zip_entry_name($file), $db->getPrefix()) === false)
{
zip_entry_close($file);
@zip_close($zip);
throw new \RuntimeException('Unable to find prefix');
}

zip_entry_close($file);
}

@zip_close($zip);
}

/**
* Import all the database via XML
*
* @param string $file A zip archive to extract
*
* @return boolean
*
* @since __DEPLOY_VERSION__
*/
public function import($file)
{
// Specify the title of the message
$title = sprintf('[%s]', Text::sprintf('COM_INSTALLER_VIEW_DEFAULT_TAB_IMPORT'));

$app = Factory::getApplication();
$db = $this->getDbo();

// Make sure that file uploads are enabled in php.
if (!(bool) ini_get('file_uploads'))
{
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_INSTALL_WARNINSTALLFILE'), 'error');

return false;
}

$tmpFile = $app->get('tmp_path') . '/' . $file['name'];

try
{
File::upload($file['tmp_name'], $tmpFile);
}
catch (FilesystemException $e)
{
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_UPLOAD_ERROR', $file['name']), 'error');

return false;
}

try
{
$this->checkZipFile($tmpFile);
}
catch (\RuntimeException $e)
{
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_CHECK_ERROR', $e->getMessage()), 'error');
unlink($tmpFile);

return false;
}

$destDir = Path::clean($app->get('tmp_path') . '/');
$zipArchive = (new Archive)->getAdapter('zip');

try
{
$zipArchive->extract($tmpFile, $destDir);
}
catch (\RuntimeException $e)
{
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_EXTRACT_ERROR', $tmpFile, $destDir), 'error');
unlink($tmpFile);

return false;
}

try
{
$importer = $db->getImporter()
->withStructure()
->asXml();
}
catch (UnsupportedAdapterException $e)
{
unlink($tmpFile);

return false;
}

$tables = Folder::files($destDir, '\.xml$');

foreach ($tables as $table)
{
$tableFile = $destDir . '/' . $table;
$tableName = str_replace('.xml', '', $table);
$importer->from(file_get_contents($tableFile));

try
{
$db->dropTable($tableName, true);
}
catch (ExecutionFailureException $e)
{
unlink($tableFile);
unlink($tmpFile);
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_DROP_ERROR', $tableName), 'error');

return false;
}

try
{
$importer->mergeStructure();
}
catch (\Exception $e)
{
unlink($tableFile);
unlink($tmpFile);
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_MERGE_ERROR', $tableName), 'error');

return false;
}

try
{
$importer->importData();
}
catch (\Exception $e)
{
unlink($tableFile);
unlink($tmpFile);
$app->enqueueMessage($title, 'error');
$app->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_DATABASE_IMPORT_DATA_ERROR', $tableName), 'error');

return false;
}

unlink($tableFile);
}

unlink($tmpFile);

return true;
}

/**
* Gets the changeset array.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public function display($tpl = null)
// Get the application
$app = Factory::getApplication();

// Specify the title of the message
$title = sprintf('[%s]', Text::sprintf('COM_INSTALLER_VIEW_DEFAULT_TAB_FIX'));

// Get data from the model.
/** @var DatabaseModel $model */
$model = $this->getModel();
Expand All @@ -92,6 +95,7 @@ public function display($tpl = null)
}
catch (\Exception $exception)
{
$app->enqueueMessage($title, 'error');
$app->enqueueMessage($exception->getMessage(), 'error');
}

Expand All @@ -102,9 +106,16 @@ public function display($tpl = null)

if ($this->changeSet)
{
($this->errorCount === 0)
? $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_OK'), 'info')
: $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_ERRORS'), 'warning');
if ($this->errorCount === 0)
{
$app->enqueueMessage($title);
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_OK'));
}
else
{
$app->enqueueMessage($title, 'warning');
$app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_ERRORS'), 'warning');
}
}

parent::display($tpl);
Expand All @@ -124,6 +135,8 @@ protected function addToolbar()
*/
ToolbarHelper::custom('database.fix', 'refresh', '', 'COM_INSTALLER_TOOLBAR_DATABASE_FIX', true);
ToolbarHelper::divider();
ToolbarHelper::custom('database.export', 'download', 'download', 'COM_INSTALLER_TOOLBAR_DATABASE_EXPORT', false);
ToolbarHelper::divider();
parent::addToolbar();
ToolbarHelper::help('Information:_Database');
}
Expand Down
Loading