%PDF- %PDF-
Direktori : /home/lightco1/www/plugins/csviaddon/csvi/com_csvi/model/ |
Current File : /home/lightco1/www/plugins/csviaddon/csvi/com_csvi/model/maintenance.php |
<?php /** * @package CSVI * @subpackage Maintenance * * @author Roland Dalmulder <contact@csvimproved.com> * @copyright Copyright (C) 2006 - 2016 RolandD Cyber Produksi. All rights reserved. * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html * @link http://www.csvimproved.com */ defined('_JEXEC') or die; /** * Performs CSVI specific maintenance operations. * * @package CSVI * @subpackage Maintenace * @since 6.0 */ class Com_CsviMaintenance { /** * Database connector * * @var JDatabaseDriver * @since 6.0 */ private $db = null; /** * Logger helper * * @var CsviHelperLog * @since 6.0 */ private $log = null; /** * CSVI Helper. * * @var CsviHelperCsvi * @since 6.0 */ private $csvihelper = null; /** * Key tracker * * @var int * @since 6.0 */ private $key = 0; /** * Hold the message to show on a JSON run * * @var string * @since 6.0 */ private $message = ''; /** * Set if we are running in CLI mode * * @var bool * @since 6.0 */ private $isCli = false; /** * Set download file * * @var bool * @since 6.6.0 */ private $downloadfile = ''; /** * Constructor. * * @param JDatabaseDriver $db Joomla Database connector * @param CsviHelperLog $log An instance of CsviHelperLog * @param CsviHelperCsvi $csvihelper An instance of CsviHelperCsvi * @param bool $isCli Set if we are running CLI mode * * @since 6.0 */ public function __construct(JDatabaseDriver $db, CsviHelperLog $log, CsviHelperCsvi $csvihelper, $isCli = false) { // Load the database class $this->db = $db; $this->log = $log; $this->csvihelper = $csvihelper; $this->isCli = $isCli; } /** * Load a number of maintenance tasks. * * @return array The list of available tasks. * * @since 6.0 */ public function getOperations() { return array('options' => array( '' => JText::_('COM_CSVI_MAKE_CHOICE'), 'loadpatch' => JText::_('COM_CSVI_PATCH_FILE_LABEL'), 'updateavailablefields' => JText::_('COM_CSVI_UPDATEAVAILABLEFIELDS_LABEL'), 'cleantemp' => JText::_('COM_CSVI_CLEANTEMP_LABEL'), 'icecatindex' => JText::_('COM_CSVI_ICECATINDEX_LABEL'), 'backuptemplates' => JText::_('COM_CSVI_BACKUPTEMPLATES_LABEL'), 'restoretemplates' => JText::_('COM_CSVI_RESTORETEMPLATES_LABEL'), 'exampletemplates' => JText::_('COM_CSVI_EXAMPLETEMPLATES_LABEL'), 'optimizetables' => JText::_('COM_CSVI_OPTIMIZETABLES_LABEL'), 'deletetables' => JText::_('COM_CSVI_DELETETABLES_LABEL') ) ); } /** * Load the options for a selected operation. * * @param string $operation The operation to get the options for * * @return string the options for a selected operation. * * @since 6.0 */ public function getOptions($operation) { switch ($operation) { case 'loadpatch': return ' <div class="control-group"> <label for="template_name" class="control-label "> ' . JText::_('COM_CSVI_CHOOSE_PATCH_FILE_LABEL') . ' </label> <div class="controls"> <input type="file" name="form[patch_file]" id="file" class="span5" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_CHOOSE_PATCH_FILE_DESC') . '</span> </div> </div>'; break; case 'updateavailablefields': return '<span class="help-block" style="display: none;">' . JText::_('COM_CSVI_UPDATE_AVAILABLEFIELDS_DESC') . '</span>'; break; case 'cleantemp': return '<span class="help-block" style="display: none;">' . JText::_('COM_CSVI_CLEANTEMP_DESC') . '</span>'; break; case 'backuptemplates': $html = '<div class="control-group "> <label class="control-label" for="exportto"> ' . JText::_('COM_CSVI_JFORM_EXPORTTO_LABEL') . ' </label> <div class="controls"> <select id="jform_exportto" name="form[exportto]" onchange="Csvi.showExportSource(this.value)"> <option value="todownload" selected="selected">' . JText::_('COM_CSVI_EXPORT_TO_DOWNLOAD_LABEL') . '</option> <option value="tofile">' . JText::_('COM_CSVI_EXPORT_TO_LOCAL_LABEL') . '</option> </select> </div> </div> <div class="control-group" id="localfield" style="display:none"> <label for="template_name" class="control-label "> ' . JText::_('COM_CSVI_CHOOSE_BACKUP_LOCATION_LABEL') . ' </label> <div class="controls"> <input type="text" name="backup_location" id="backup_location" value="' . JPATH_SITE . '/tmp/com_csvi" class="input-xxlarge" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_CHOOSE_BACKUP_LOCATION_DESC') . '</span> </div> </div>'; // Load the list of templates /** @var CsviModelTemplates $templateModel */ $templateModel = JModelLegacy::getInstance('Templates', 'CsviModel'); $templates = $templateModel->getTemplates(); $html .= '<div class="control-group"> <label for="template_name" class="control-label "> ' . JText::_('COM_CSVI_BACKUPTEMPLATES_LABEL') . ' </label> <div class="controls"> <input type="checkbox" onclick="Joomla.checkAll(this)" checked="checked" title="' . JText::_('COM_CSVI_CHECK_ALL_FIELDS') . '" value="" name="checkall-toggle" /> ' . JText::_('COM_CSVI_CHECK_ALL_FIELDS') . ' <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_BACKUPTEMPLATES_DESC') . '</span> </div> </div> <div class="span12">'; foreach ($templates as $key => $template) { if ($key > 0) { if (empty($template->value)) { if ($key > 1) { $html .= '</ul></div>'; } $html .= '<div class="span5"><label>' . $template->text . '</label> <ul class="unstyled">'; } else { $html .= ' <li> <label> <input type="checkbox" checked="checked" name="form[templates][]" id="cb' . $key . '" value="' . $template->value . '" /> ' . $template->text . ' </label>' . '</li>'; } } } $html .= '</div>'; return $html; break; case 'restoretemplates': return ' <div class="control-group"> <label for="template_name" class="control-label "> ' . JText::_('COM_CSVI_CHOOSE_RESTORE_FILE_LABEL') . ' </label> <div class="controls"> <input type="file" name="form[restore_file]" id="file" class="span5" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_CHOOSE_RESTORE_FILE_DESC') . '</span> </div> </div>'; break; case 'icecatindex': $html = ' <div class="span12"> <h3>' . JText::_('COM_CSVI_MAINTENANCE_ICECAT') . '</h3> <div class="control-group"> <label class="control-label" for="icecatlocation"> ' . JText::_('COM_CSVI_ICECAT_LOCATION_LABEL') . ' </label> <div class="controls"> <input type="text" id="icecatlocation" name="form[icecatlocation]" value="' . CSVIPATH_TMP . '" class="input-xxlarge" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_LOCATION_DESC') . '</span> </div> </div> <div class="control-group"> <label class="control-label" for="form_icecat_gzip"> ' . JText::_('COM_CSVI_ICECAT_GZIP_LABEL') . ' </label> <div class="controls"> ' . JHtml::_('select.booleanlist', 'form[icecat_gzip]', '', 1) . ' <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_GZIP_DESC') . '</span> </div> </div> <div> <div class="span12"> <h3>' . JText::_('COM_CSVI_MAINTENANCE_ICECAT_FILE') . '</h3> <div class="control-group"> <label class="control-label" for="icecatfile"> ' . JText::_('COM_CSVI_ICECAT_FILE_LABEL') . ' </label> <div class="controls"> <input type="checkbox" id="icecatfile" name="form[icecat][]" value="icecat_index" checked="checked" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_FILE_DESC') . '</span> </div> </div> <div class="control-group"> <label class="control-label" for="form_loadtype"> ' . JText::_('COM_CSVI_ICECAT_FILE_LOAD_LABEL') . ' </label> <div class="controls"> ' . JHtml::_('select.booleanlist', 'form[loadtype]', '', 0, JText::_('COM_CSVI_ICECAT_FILE_SINGLE'), JText::_('COM_CSVI_ICECAT_FILE_FULL')) . ' <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_FILE_LOAD_DESC') . '</span> </div> </div> <div class="control-group"> <label class="control-label" for="icecat_records"> ' . JText::_('COM_CSVI_ICECAT_FILE_LOAD_RECORDS_LABEL') . ' </label> <div class="controls"> <input type="text" id="icecat_records" name="form[icecat_records]" value="1000" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_FILE_LOAD_RECORDS_DESC') . '</span> </div> </div> <div class="control-group"> <label class="control-label" for="icecat_wait"> ' . JText::_('COM_CSVI_ICECAT_FILE_LOAD_WAIT_LABEL') . ' </label> <div class="controls"> <input type="text" id="icecat_wait" name="form[icecat_wait]" value="5" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_FILE_LOAD_WAIT_DESC') . '</span> </div> </div> <div> <div class="span12"> <h3>' . JText::_('COM_CSVI_MAINTENANCE_ICECAT_SUPPLIER') . '</h3> <div class="control-group"> <label class="control-label" for="icecat_supplier"> ' . JText::_('COM_CSVI_ICECAT_SUPPLIER_LABEL') . ' </label> <div class="controls"> <input type="checkbox" id="icecat_supplier" name="form[icecat][]" value="icecat_supplier" checked="checked" /> <span class="help-block" style="display: none;">' . JText::_('COM_CSVI_ICECAT_SUPPLIER_DESC') . '</span> </div> </div> <div>'; return $html; break; case 'deletetables': $layout = new JLayoutFile('csvi.modal'); return $layout->render( array( 'modal-header' => JText::_('COM_CSVI_' . $operation . '_LABEL'), 'modal-body' => JText::_('COM_CSVI_CONFIRM_TABLES_DELETE'), 'cancel-button' => true ) ); break; case 'optimizetables': return JText::_('COM_CSVI_OPTIMIZETABLES_DESC'); break; case 'exampletemplates': return JText::_('COM_CSVI_EXAMPLETEMPLATES_DESC'); break; default: return ''; break; } } /** * Optimize all database tables. * * @param FOFInput $input The input model * @param mixed $key A reference used by the method. * * @return bool Always returns true. * * @since 6.0 */ public function optimizeTables(FOFInput $input, $key) { // Get the list of tables to optimize $tables = $this->db->getTableList(); if ($this->isCli) { foreach ($tables as $table) { // Increment log linecounter $this->log->incrementLinenumber(); $this->optimizeTable($table); } } else { if (isset($tables[$key])) { // Increment log linecounter $this->log->incrementLinenumber(); if ($this->optimizeTable($tables[$key])) { $this->message = JText::sprintf('COM_CSVI_TABLE_HAS_BEEN_OPTIMIZED', $tables[$key]); } else { $this->message = JText::sprintf('COM_CSVI_TABLE_HAS_NOT_BEEN_OPTIMIZED', $tables[$key]); } // Set the key for post processing $key++; $this->key = $key; } else { $this->key = false; } } return true; } /** * Optimize a table. * * @param string $table The name of the table to optimize * * @return bool True on success | False on failure. * * @since 6.0 */ private function optimizeTable($table) { // Build the query $q = 'OPTIMIZE TABLE ' . $this->db->quoteName($table); $this->db->setQuery($q); // Execute query if ($this->db->execute()) { $this->log->addStats('information', JText::sprintf('COM_CSVI_TABLE_HAS_BEEN_OPTIMIZED', $table), $table); return true; } else { $this->log->addStats('incorrect', JText::sprintf('COM_CSVI_TABLE_HAS_NOT_BEEN_OPTIMIZED', $table), $table); return false; } } /** * Post processing optimize tables. * * @return array Settings for continuing. * * @since 6.0 */ public function onAfteroptimizeTables() { if ($this->key) { // Return data $results = array(); $results['continue'] = true; $results['key'] = $this->key; } else { $results['continue'] = false; } $results['info'] = $this->message; return $results; } /** * Update available fields. * * @param FOFInput $input The input model * @param mixed $key A reference used by the method. * * @return bool True on success, false on failure. * * @since 3.3 * * @throws \RuntimeException */ public function updateAvailableFields(FOFInput $input, $key) { $result = false; // Check if we need to prepare the available fields if ($key === 0) { $this->prepareAvailableFields(); } // Check if we are running a cron job list($isCli, $isAdmin) = FOFDispatcher::isCliAdmin(); if ($isCli) { $continue = true; while ($continue) { $result = $this->indexAvailableFields(); $continue = $input->get('continue'); } } else { $result = $this->indexAvailableFields(); } return $result; } /** * Prepare for available fields importing. * * 1. Set all tables to be indexed * 2. Empty the available fields table * 3. Import the extra availablefields sql file * 4. Find what tables need to be imported and store them in the session. * * @return void. * * @since 3.5 * * @throws \RuntimeException */ private function prepareAvailableFields() { // Set all tables to be indexed $query = $this->db->getQuery(true) ->update($this->db->quoteName('#__csvi_availabletables')) ->set($this->db->quoteName('indexed') . ' = 0'); $this->db->setQuery($query)->execute(); // Drop the available fields first try { // Delete the table $this->db->dropTable('#__csvi_availablefields'); $this->log->addStats('delete', 'COM_CSVI_AVAILABLE_FIELDS_TABLE_DELETED', 'availablefields'); // Create table again so index is proper if ($this->createAvailableFieldsTable()) { // Index the custom tables used in CSVI import/export $this->indexCustomTables(); // Do component specific updates $override = new stdClass; $override->value = 'custom'; $components = $this->csvihelper->getComponents(); $components[] = $override; jimport('joomla.filesystem.file'); foreach ($components as $component) { // Load any component specific file if ($component->value && $component->value !== 'com_csvi' && $component->value !== 'custom' && file_exists(JPATH_ADMINISTRATOR . '/components/com_csvi/addon/' . $component->value . '/model/maintenance.php')) { require_once JPATH_ADMINISTRATOR . '/components/com_csvi/addon/' . $component->value . '/model/maintenance.php'; $extensionClassname = ucfirst($component->value) . 'Maintenance'; $extensionModel = new $extensionClassname($this->db, $this->log, $this->csvihelper); if (method_exists($extensionModel, 'updateAvailableFields')) { $extensionModel->updateAvailableFields(); } } // Process all extra available fields $filename = JPATH_ADMINISTRATOR . '/components/com_csvi/addon/' . $component->value . '/install/availablefields.sql'; if (JFile::exists($filename)) { // Check if the component is installed $ext_id = true; if (0 === strpos($component->value, 'com_')) { $query = $this->db->getQuery(true) ->select($this->db->quoteName('extension_id')) ->from($this->db->quoteName('#__extensions')) ->where($this->db->quoteName('element') . ' = ' . $this->db->quote($component->value)); $this->db->setQuery($query); $ext_id = $this->db->loadResult(); } if ($ext_id) { // Increment line number $this->log->incrementLinenumber(); $queries = JDatabaseDriver::splitSql(file_get_contents($filename)); foreach ($queries as $step => $splitQuery) { // Clean the string of any trailing whitespace $splitQuery = trim($splitQuery); if ($splitQuery) { $this->db->setQuery($splitQuery); if ($this->db->execute()) { $this->log->addStats( 'added', JText::sprintf('COM_CSVI_CUSTOM_AVAILABLE_FIELDS_HAVE_BEEN_ADDED', JText::_('COM_CSVI_' . $component->value), $step + 1), $component->value . '_CUSTOM' ); } else { $this->log->add( 'incorrect', JText::sprintf('COM_CSVI_CUSTOM_AVAILABLE_FIELDS_HAVE_NOT_BEEN_ADDED', JText::_('COM_CSVI_' . $component->value), $step + 1, $splitQuery), $component->value . '_CUSTOM' ); } } } // Execute any specific available fields that are not in an SQL file if (file_exists(JPATH_ADMINISTRATOR . '/components/com_csvi/addon/' . $component->value . '/model/maintenance.php')) { require_once JPATH_ADMINISTRATOR . '/components/com_csvi/addon/' . $component->value . '/model/maintenance.php'; $classname = $component->value . 'Maintenance'; $addon = new $classname($this->db, $this->log, $this->csvihelper); if (method_exists($addon, 'customAvailableFields')) { $addon->customAvailableFields(); } } } } } // Increment line number $this->log->decrementLinenumber(); } } catch (Exception $e) { $this->log->addStats('error', $e->getMessage(), 'availablefields'); } } /** * Process the custom tables for import/export. * * @return void. * * @since 6.5.6 * * @throws \RuntimeException */ private function indexCustomTables() { // Add the custom fields for each specific custom table in use $query = $this->db->getQuery(true) ->select($this->db->quoteName('template_table')) ->from($this->db->quoteName('#__csvi_availabletables')) ->where($this->db->quoteName('task_name') . ' = ' . $this->db->quote('custom')) ->where($this->db->quoteName('component') . ' = ' . $this->db->quote('com_csvi')) ->where($this->db->quoteName('action') . ' = ' . $this->db->quote('import')); $this->db->setQuery($query); $importTables = $this->db->loadColumn(); $query->clear('where') ->where($this->db->quoteName('task_name') . ' = ' . $this->db->quote('custom')) ->where($this->db->quoteName('component') . ' = ' . $this->db->quote('com_csvi')) ->where($this->db->quoteName('action') . ' = ' . $this->db->quote('export')); $this->db->setQuery($query); $exportTables = $this->db->loadColumn(); $query = 'INSERT IGNORE INTO ' . $this->db->quoteName('#__csvi_availablefields') . '(' . $this->db->quoteName('csvi_name') . ', ' . $this->db->quoteName('component_name') . ', ' . $this->db->quoteName('component_table') . ', ' . $this->db->quoteName('component') . ', ' . $this->db->quoteName('action') . ')'; $customFields = array(); foreach ($importTables as $importTable) { // Add the custom available fields for each import table $customFields[] = '(' . $this->db->quote('skip') . ', ' . $this->db->quote('skip') . ', ' . $this->db->quote($importTable) . ', ' . $this->db->quote('com_csvi') . ', ' . $this->db->quote('import') . ')'; $customFields[] = '(' . $this->db->quote('combine') . ', ' . $this->db->quote('combine') . ', ' . $this->db->quote($importTable) . ', ' . $this->db->quote('com_csvi') . ', ' . $this->db->quote('import') . ')'; } foreach ($exportTables as $exportTable) { // Add the custom available fields for each export table $customFields[] = '(' . $this->db->quote('custom') . ', ' . $this->db->quote('custom') . ', ' . $this->db->quote($exportTable) . ', ' . $this->db->quote('com_csvi') . ', ' . $this->db->quote('export') . ')'; } if (0 !== count($customFields)) { $query .= ' VALUES ' . implode(', ', $customFields); $this->db->setQuery($query)->execute(); } } /** * Import the available fields in steps. * * @return bool True on success | False on failure. * * @since 3.5 * * @throws \RuntimeException */ private function indexAvailableFields() { // Load the session data $lines = $this->log->getLinenumber(); $lines++; // Set the line number $this->log->setLinenumber($lines); $query = $this->db->getQuery(true); $query->select( $this->db->quoteName('csvi_availabletable_id') . ',' . $this->db->quoteName('template_table') . ',' . $this->db->quoteName('component') . ',' . $this->db->quoteName('action') ) ->from($this->db->quoteName('#__csvi_availabletables')) ->where($this->db->quoteName('indexed') . ' = 0') ->where($this->db->quoteName('enabled') . ' = 1') ->group($this->db->quoteName('template_table')); $this->db->setQuery($query, 0, 1); $table = $this->db->loadObject(); if (is_object($table)) { // Set the key that we started $this->key = 1; // Check if the table exists $tables = $this->db->getTableList(); if (in_array($this->db->getPrefix() . $table->template_table, $tables, true)) { // Increment line number $this->log->incrementLinenumber(); $this->indexTable($table); } else { $this->message = $table->template_table . ' not an available table'; } // Set the table to indexed $query = $this->db->getQuery(true); $query->update($this->db->quoteName('#__csvi_availabletables')) ->set($this->db->quoteName('indexed') . ' = 1') ->where($this->db->quoteName('csvi_availabletable_id') . ' = ' . (int) $table->csvi_availabletable_id); $this->db->setQuery($query); $this->db->execute(); } else { $this->key = false; } return true; } /** * Creates an array of custom database fields the user can use for import/export. * * @param string $table The table name to get the fields for * @param bool $addname Add the table name to the list of fields * * @return array List of custom database fields. * * @since 3.0 */ private function dbFields($table, $addname=false) { $customfields = array(); $q = 'SHOW COLUMNS FROM ' . $this->db->quoteName('#__' . $table); $this->db->setQuery($q); $fields = $this->db->loadObjectList(); if (count($fields) > 0) { foreach ($fields as $field) { if ($addname) { $customfields[$field->Field] = $table; } else { $customfields[$field->Field] = null; } } } return $customfields; } /** * Index a single table. * * @param object $table The table to index * * @return void. * * @since 6.0 * * @throws \RuntimeException */ public function indexTable($table) { // Get the primary key for the table $primaryKey = $this->csvihelper->getPrimaryKey($table->template_table); // Load the language $this->csvihelper->loadLanguage($table->component, false); $fields = $this->dbFields($table->template_table, true); if (is_array($fields)) { // Process all fields foreach ($fields as $name => $value) { // Check if the field is a primary field $primary = 0; if ($primaryKey === $name) { $primary = 1; } if ($name) { $q = 'INSERT IGNORE INTO ' . $this->db->quoteName('#__csvi_availablefields') . ' VALUES (' . '0,' . $this->db->quote($name) . ',' . $this->db->quote($name) . ',' . $this->db->quote($value) . ',' . $this->db->quote($table->component) . ',' . $this->db->quote($table->action) . ',' . $this->db->quote($primary) . ')'; $this->db->setQuery($q); if ($this->db->execute()) { $this->log->addStats( 'added', JText::sprintf('COM_CSVI_AVAILABLE_FIELDS_HAVE_BEEN_ADDED', $table->template_table), 'maintenance_index_availablefields' ); $this->message = JText::sprintf('COM_CSVI_AVAILABLE_FIELDS_HAVE_BEEN_ADDED', $table->template_table); } else { $this->log->addStats('error', 'COM_CSVI_AVAILABLE_FIELDS_HAVE_NOT_BEEN_ADDED', 'maintenance_index_availablefields'); $this->message = $this->db->getErrorMsg(); } } } } } /** * This is called after the available fields have been updated for post-processing. * * @return bool Always true. * * @since 6.0 */ public function onAfterUpdateAvailableFields() { if ($this->key) { // Return data $results = array(); $results['continue'] = true; $results['key'] = $this->key; } else { $results['continue'] = false; } $results['info'] = $this->message; return $results; } /** * Load a patch provided by the forum. * * @param FOFInput $input The FOFInput class. * * @return bool True on success, false on failure. * * throws RuntimeException * * @since 5.6 */ public function loadPatch(FOFInput $input) { // Load the necessary libraries jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.archive'); clearstatcache(); // Get the uploaded details $upload = $input->get('patch_file', false); // Check if the file upload has an error if (empty($upload)) { $this->log->addStats('incorrect', 'COM_CSVI_NO_UPLOADED_FILE_PROVIDED', 'maintenance'); return false; } elseif ($upload['error'] == 0) { // Get some basic info $folder = CSVIPATH_TMP . '/patch/' . time(); // Create the temp folder if (JFolder::create($folder)) { // Move the uploaded file to its temp location if (JFile::copy($upload['tmp_name'], $folder . '/' . $upload['name'])) { // Remove the temporary file JFile::delete($upload['tmp_name']); // Unpack the archive if (JArchive::extract($folder . '/' . $upload['name'], $folder)) { // File is unpacked, remove the zip file so it won't get processed JFile::delete($folder . '/' . $upload['name']); // File is unpacked, let's process the folder if ($this->processFolder($folder, $folder)) { // All good remove tempory folder JFolder::delete($folder); return true; } } else { $this->log->addStats('incorrect', 'COM_CSVI_CANNOT_UNPACK_UPLOADED_FILE', 'maintenance'); throw new RuntimeException(JText::_('COM_CSVI_CANNOT_UNPACK_UPLOADED_FILE')); } } } else { $this->log->addStats('incorrect', JText::sprintf('COM_CSVI_CANNOT_CREATE_UNPACK_FOLDER', $folder), 'maintenance'); throw new RuntimeException(JText::sprintf('COM_CSVI_CANNOT_CREATE_UNPACK_FOLDER', $folder)); } } else { // There was a problem uploading the file switch ($upload['error']) { case '1': $this->log->addStats('incorrect', 'COM_CSVI_THE_UPLOADED_FILE_EXCEEDS_THE_MAXIMUM_UPLOADED_FILE_SIZE', 'maintenance'); break; case '2': $this->log->addStats('incorrect', 'COM_CSVI_THE_UPLOADED_FILE_EXCEEDS_THE_MAXIMUM_UPLOADED_FILE_SIZE', 'maintenance'); break; case '3': $this->log->addStats('incorrect', 'COM_CSVI_THE_UPLOADED_FILE_WAS_ONLY_PARTIALLY_UPLOADED', 'maintenance'); break; case '4': $this->log->addStats('incorrect', 'COM_CSVI_NO_FILE_WAS_UPLOADED', 'maintenance'); break; case '6': $this->log->addStats('incorrect', 'COM_CSVI_MISSING_A_TEMPORARY_FOLDER', 'maintenance'); break; case '7': $this->log->addStats('incorrect', 'COM_CSVI_FAILED_TO_WRITE_FILE_TO_DISK', 'maintenance'); break; case '8': $this->log->addStats('incorrect', 'COM_CSVI_FILE_UPLOAD_STOPPED_BY_EXTENSION', 'maintenance'); break; default: $this->log->addStats('incorrect', 'COM_CSVI_THERE_WAS_A_PROBLEM_UPLOADING_THE_FILE', 'maintenance'); break; } throw new RuntimeException(JText::_('COM_CSVI_PATH_UPLOAD_ERROR')); } return true; } /** * Walk through a folder to process all found files. * * @param string $folder The name of the folder to process * @param string $base The base folder * * @return bool True on success, false on failure. * * @since 5.6 */ private function processFolder($folder, $base = null) { $foundfiles = scandir($folder); foreach ($foundfiles as $ffkey => $ffname) { $src = $folder . '/' . $ffname; // Check if it is a folder if (is_dir($src)) { switch ($ffname) { case '.': case '..': break; default: $this->processFolder($src, $base); break; } } else { // Create the destination name $destFile = str_ireplace($base, JPATH_SITE, $folder) . '/' . $ffname; // Check if the destination file exists if (file_exists($destFile)) { JFile::move($destFile, $destFile . '.' . date('Ymd-His')); } // Copy the file to the destination location if (JFile::copy($src, $destFile)) { $this->log->addStats('added', JText::sprintf('COM_CSVI_COPY_PATCHFILE', $src, $destFile), 'maintenance'); } else { $this->log->addStats('incorrect', JText::sprintf('COM_CSVI_CANT_COPY_PATCHFILE', $src, $destFile), 'maintenance'); } } } return true; } /** * Clean the CSVI cache. * * @return bool Always returns true. * * @since 3.0 */ public function cleanTemp() { jimport('joomla.filesystem.file'); jimport('joomla.filesystem.folder'); $folder = CSVIPATH_TMP; if (JFolder::exists($folder)) { // Delete all import files left behind in the folder JFile::delete(JFolder::files($folder, '.', false, true)); // Delete all import folders left behind in the folder $folders = JFolder::folders($folder, '.', true, true, array('debug', 'export')); if (!empty($folders)) { foreach ($folders as $path) { JFolder::delete($path); } } // Empty the export folder JFile::delete(JFolder::files($folder . '/export', '.', false, true)); // Load the files if (JFolder::exists(CSVIPATH_DEBUG)) { $files = JFolder::files(CSVIPATH_DEBUG, 'com_csvi', false, true); if ($files) { // Set all directory separators in the same direction foreach ($files as &$file) { $file = str_replace('\\', '/', $file); } // Remove any debug logs that are still there but not in the database $query = $this->db->getQuery(true) ->select( 'CONCAT(' . $this->db->quote(CSVIPATH_DEBUG . '/com_csvi.log.') . ', ' . $this->db->quoteName('csvi_log_id') . ', ' . $this->db->quote('.php') . ') AS ' . $this->db->quoteName('filename') ) ->from($this->db->quoteName('#__csvi_logs')) ->order($this->db->quoteName('csvi_log_id')); $this->db->setQuery($query); $ids = $this->db->loadColumn(); if (!is_array($ids)) { $ids = (array) $ids; } // Delete all obsolete files JFile::delete(array_diff($files, $ids)); } } $this->log->addStats('delete', JText::sprintf('COM_CSVI_TEMP_CLEANED', $folder, CSVIPATH_DEBUG, $folder . '/export'), 'maintenance'); } else { $this->log->addStats('information', JText::sprintf('COM_CSVI_TEMP_PATH_NOT_FOUND'), 'maintenance'); } return true; } /** * Backup selected templates. * * @param FOFInput $input FOFInput object * * @return bool Always true. * * @since 3.0 * * @throws CsviException * @throws RuntimeException * @throws UnexpectedValueException */ public function backupTemplates(FOFInput $input) { $lineNumber = 1; $ids = $input->get('templates', array(), 'array'); if (!$ids) { throw new CsviException(JText::_('COM_CSVI_NO_TEMPLATES_SELECTED')); } $xml = new DOMDocument; $xml->formatOutput = true; $csvi_element = $xml->createElement('csvi'); /** @var CsviModelTemplates $templateModel */ $templateModel = JModelLegacy::getInstance('Templates', 'CsviModel', array('ignore_request' => true)); $templates = $templateModel->getItems(); $ignoreFields = array('ftpusername', 'ftppass', 'urlusername', 'urlpass', 'secret'); foreach ($templates as $template) { $template = (array) $template; if (in_array($template['csvi_template_id'], $ids, true)) { // Create the template node $xml_template = $xml->createElement('template'); // Add the settings $template_settings = $xml->createElement('settings'); $settings = json_decode($template['settings']); foreach ($settings as $name => $value) { if (in_array($name, $ignoreFields, true)) { $value = ''; } $ruleElement = $xml->createElement($name); if (is_array($value)) { foreach ($value as $key => $subValue) { $subElement = $xml->createElement('option'); $subElement->appendChild($xml->createCDATASection($subValue)); $ruleElement->appendChild($subElement); } } else { // Convert 1/0 to yes/no so 0 wont become empty switch ($value) { case '0': $val = 'no'; break; case '1': $val = 'yes'; break; default: $val = $value; break; } $ruleElement->appendChild($xml->createCDATASection($val)); } $template_settings->appendChild($ruleElement); } // Add the settings to the XML $xml_template->appendChild($template_settings); // Array of fields to export $nodes = array( 'template_name', 'advanced', 'action', 'frontend', 'secret', 'log', 'lastrun', 'enabled', 'ordering', ); // Add all the template options foreach ($nodes as $ruleNode) { if (in_array($ruleNode, $ignoreFields, true)) { $template[$ruleNode] = ''; } $ruleElement = $xml->createElement($ruleNode); $ruleElement->appendChild($xml->createCDATASection($template[$ruleNode])); $xml_template->appendChild($ruleElement); } // Add the fields for this template $fieldsModel = JModelLegacy::getInstance('Templatefields', 'CsviModel', array('ignore_request' => true)); $fieldsModel->setState('filter.csvi_template_id', $template['csvi_template_id']); $fields = $fieldsModel->getItems(); if (count($fields) > 0) { $nodes = array( 'field_name', 'xml_node', 'column_header', 'default_value', 'enabled', 'sort', 'cdata', 'ordering', ); $template_fields = $xml->createElement('fields'); foreach ($fields as $field) { $template_field = $xml->createElement('field'); foreach ($nodes as $node) { if (isset($field->$node)) { $fieldElement = $xml->createElement($node); $fieldElement->appendChild($xml->createCDATASection($field->$node)); $template_field->appendChild($fieldElement); } } // Add the template field rules $query = $this->db->getQuery(true) ->select( $this->db->quoteName( array( 'name', 'action', 'ordering', 'plugin', 'plugin_params', ) ) ) ->from($this->db->quoteName('#__csvi_rules', 'r')) ->leftJoin( $this->db->quoteName('#__csvi_templatefields_rules', 't') . ' ON ' . $this->db->quoteName('t.csvi_rule_id') . ' = ' . $this->db->quoteName('r.csvi_rule_id') ) ->where($this->db->quoteName('t.csvi_templatefield_id') . ' = ' . (int) $field->csvi_templatefield_id); $this->db->setQuery($query); $rules = $this->db->loadObjectList(); if (count($rules) > 0) { $ruleNodes = array( 'name', 'action', 'ordering', 'plugin', 'plugin_params', ); $fieldRules = $xml->createElement('fieldrules'); foreach ($rules as $rule) { $fieldRule = $xml->createElement('rule'); foreach ($ruleNodes as $ruleNode) { $ruleElement = $xml->createElement($ruleNode); if ($ruleNode === 'plugin_params') { $params = json_decode($rule->$ruleNode); if (is_object($params)) { foreach ($params as $name => $value) { $element_param = $xml->createElement($name); $element_param->appendChild($xml->createCDATASection($value)); $ruleElement->appendChild($element_param); } } } else { $ruleElement->nodeValue = $rule->$ruleNode; } $fieldRule->appendChild($ruleElement); } $fieldRules->appendChild($fieldRule); } $template_field->appendChild($fieldRules); } $template_fields->appendChild($template_field); } // Add the fields to the XML $xml_template->appendChild($template_fields); } // Add the template to the XML $this->log->setLinenumber($lineNumber++); $csvi_element->appendChild($xml_template); } } $xml->appendChild($csvi_element); $location = $input->get('exportto', 'todownload', 'string'); // Create the backup file $filePath = JPATH_SITE . $input->get('backup_location', '/tmp/com_csvi', 'string'); $filename = 'csvi_templates_' . date('Ymd', time()) . '.xml'; $file = JPath::clean($filePath . '/' . $filename, '/'); $xml->save($file); $this->downloadfile = ''; // If user needs to download the file if ($location === 'todownload') { $this->downloadfile = JUri::root() . 'administrator/index.php?option=com_csvi&view=exports&task=downloadfile&tmpl=component&file=' . base64_encode($file); } else { $this->log->addStats('information', JText::sprintf('COM_CSVI_BACKUP_TEMPLATE_PATH', $file), 'maintenance'); } // Store the log count $lineNumber--; $input->set('logcount', $lineNumber); return true; } /** * Restore templates. * * @param FOFInput $input FOFInput object * @param mixed $key A reference used by the method. * @param string $filename A local filename to use for import * * @return bool True on success | False on failure. * * @since 3.0 */ public function restoreTemplates(FOFInput $input, $key, $filename = '') { $linenumber = 1; jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.file'); if (empty($filename)) { $upload = $input->get('restore_file', false); // Check if the file upload has an error if (empty($upload)) { $this->log->addStats('incorrect', JText::_('COM_CSVI_NO_UPLOADED_FILE_PROVIDED'), 'maintenance'); return false; } $filename = $upload['tmp_name']; } $doc = new DOMDocument; $doc->load(realpath($filename)); $data = $this->domnodeToArray($doc->documentElement); $file = basename($filename); // Check if it is a multi-dimensional array if (!isset($data['template'][0])) { // Make the array multi-dimensional $newtemplate = array(); $newtemplate['template'][0] = $data['template']; $data = $newtemplate; } // Load the necessary tables $templateTable = FOFTable::getAnInstance('templates'); $fieldTable = FOFTable::getAnInstance('templatefields'); $ruleTable = FOFTable::getAnInstance('rules'); $templatefieldrulesTable = FOFTable::getAnInstance('templatefields_rules'); foreach ($data as $templates) { foreach ($templates as $template) { // Store the template $templateTable->reset(); $templateTable->set('csvi_template_id', null); $templateTable->set('template_name', $template['template_name']); $templateTable->set('advanced', $template['advanced']); $templateTable->set('action', $template['action']); $templateTable->set('frontend', $template['frontend']); $templateTable->set('secret', $template['secret']); $templateTable->set('log', $template['log']); $templateTable->set('lastrun', $template['lastrun']); $templateTable->set('enabled', $template['enabled']); $templateTable->set('ordering', $template['ordering']); // Reformat the settings foreach ($template['settings'] as $name => $setting) { // Convert back yes/no to template readable form 1/0 switch ($template['settings'][$name]) { case 'no': $val = 0; break; case 'yes': $val = 1; break; default: $val = $template['settings'][$name]; break; } $template['settings'][$name] = $val; if (is_array($setting)) { // Make sure the option is an array $setting['option'] = (array) $setting['option']; $template['settings'][$name] = $setting['option']; } } $templateTable->set('settings', json_encode($template['settings'])); $templateTable->store(); if (array_key_exists('fields', $template)) { // Store the fields $fields = $template['fields']['field']; if (!array_key_exists(0, $template['fields']['field'])) { $fields = array(0 => $template['fields']['field']); } foreach ($fields as $field) { $fieldTable->set('csvi_template_id', $templateTable->get('csvi_template_id')); $fieldTable->save($field); // Store any field related rules if (isset($field['fieldrules'])) { foreach ($field['fieldrules'] as $rules) { if (isset($rules['name'])) { $rules = array($rules); } foreach ($rules as $rule) { $ruledata = array( 'name' => $rule['name'], 'action' => $rule['action'], 'ordering' => $rule['ordering'], 'plugin' => $rule['plugin'], 'plugin_params' => json_encode($rule['plugin_params']), 'csvi_templatefield_id' => $fieldTable->get('csvi_templatefield_id') ); // Save the rule $ruleTable->save($ruledata); // Save the relation $templatefieldrulesTable->set('csvi_templatefield_id', $fieldTable->get('csvi_templatefield_id')); $templatefieldrulesTable->set('csvi_rule_id', $ruleTable->get('csvi_rule_id')); $templatefieldrulesTable->store(); // Reset the relation table $templatefieldrulesTable->reset(); $templatefieldrulesTable->csvi_templatefields_rule_id = null; // Reset the rule table $ruleTable->reset(); $ruleTable->csvi_rule_id = null; } } } $fieldTable->reset(); $fieldTable->csvi_templatefield_id = null; } } // Increment the number of templates processed $this->log->setLinenumber($linenumber++); } } // Set the name of the file restore to logs display $this->log->setFilename($file); // Store the log count $linenumber--; $input->set('logcount', $linenumber); return true; } /** * Turn the XML file into an associative array. * * @param DOMElement $node The tree to turn into an array. * * @return array The XML layout as associative array. * * @see https://github.com/gaarf/XML-string-to-PHP-array * * @since 6.0 */ private function domnodeToArray($node) { $output = array(); switch ($node->nodeType) { case XML_CDATA_SECTION_NODE: case XML_TEXT_NODE: $output = trim($node->textContent); break; case XML_ELEMENT_NODE: for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) { $child = $node->childNodes->item($i); $v = $this->domnodeToArray($child); if (isset($child->tagName)) { $t = $child->tagName; if (!isset($output[$t])) { $output[$t] = array(); } if (empty($v)) { $v = ''; } $output[$t][] = $v; } elseif ($v) { $output = (string) $v; } } if (is_array($output)) { if ($node->attributes->length) { $a = array(); foreach ($node->attributes as $attrName => $attrNode) { $a[$attrName] = (string) $attrNode->value; } $output['@attributes'] = $a; } foreach ($output as $t => $v) { if (is_array($v) && count($v) == 1 && $t != '@attributes') { $output[$t] = $v[0]; } } } break; } return $output; } /** * Prepare the ICEcat index files for loading. * * @param FOFInput $input The input model * * @return bool True on success | False on failure. * * @since 6.0 */ public function onBeforeIcecatIndex(FOFInput $input) { $session = JFactory::getSession(); $settings = new CsviHelperSettings($this->db); $username = $settings->get('ice_username', false); $password = $settings->get('ice_password', false); $icecat_options = $input->get('icecat', array(), null); $icecat_gzip = $input->get('icecat_gzip', true, 'bool'); $loadremote_index = false; $loadremote_supplier = false; // Check which indexes to load if (in_array('icecat_index', $icecat_options)) { $load_index = true; } else { $load_index = false; } if (in_array('icecat_supplier', $icecat_options)) { $load_supplier = true; } else { $load_supplier = false; } // Check if we have a username and password if ($username && $password) { // Joomla includes jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.file'); jimport('joomla.filesystem.archive'); // Check if the files are stored on the server $location = $input->get('icecatlocation', '', 'string'); if ($load_index) { if (JFile::exists($location . '/icecat_index')) { $icecat_index_file = $location . '/icecat_index'; } elseif (JFile::exists($location . '/icecat_index.gzip')) { $icecat_index_file = $location . '/icecat_index.gzip'; } elseif (JFile::exists($location . '/icecat_index.zip')) { $icecat_index_file = $location . '/icecat_index.zip'; } else { $loadremote_index = true; } } if ($load_supplier) { if (JFile::exists($location . '/icecat_supplier')) { $icecat_supplier_file = $location . '/icecat_supplier'; } elseif (JFile::exists($location . '/icecat_supplier.gzip')) { $icecat_supplier_file = $location . '/icecat_supplier.gzip'; } elseif (JFile::exists($location . '/icecat_supplier.zip')) { $icecat_supplier_file = $location . '/icecat_supplier.zip'; } else { $loadremote_supplier = true; } } // Load the remote files if needed if ($loadremote_index || $loadremote_supplier) { // Context for retrieving files if ($icecat_gzip) { $gzip = "Accept-Encoding: gzip\r\n"; } else { $gzip = ''; } $context = stream_context_create(array( 'http' => array( 'header' => "Authorization: Basic " . base64_encode($username . ':' . $password) . "\r\n" . $gzip ) )); if ($load_index && $loadremote_index) { // ICEcat index file $icecat_url = $settings->get('icecat.ice_index', 'http://data.icecat.biz/export/freexml.int/INT/files.index.csv'); // Load the index file from the ICEcat server to a local file $icecat_index_file = CSVIPATH_TMP . '/icecat_index'; if ($icecat_gzip) { $icecat_index_file .= '.gzip'; } $fp_url = fopen($icecat_url, 'r', false, $context); $fp_local = fopen($icecat_index_file, 'w+'); while($content = fread($fp_url, 1024536)) { fwrite($fp_local, $content); } fclose($fp_url); fclose($fp_local); } if ($load_supplier && $loadremote_supplier) { // Load the manufacturer data $icecat_mf = $settings->get('icecat.ice_supplier', 'http://data.icecat.biz/export/freexml.int/INT/supplier_mapping.xml'); // Load the index file from the ICEcat server to a local file $icecat_supplier_file = CSVIPATH_TMP . '/icecat_supplier'; if ($icecat_gzip) { $icecat_supplier_file .= '.gzip'; } $fp_url = fopen($icecat_mf, 'r', false, $context); $fp_local = fopen($icecat_supplier_file, 'w+'); while($content = fread($fp_url, 1024536)) { fwrite($fp_local, $content); } fclose($fp_url); fclose($fp_local); } } // Check if we need to unpack the files if ($load_index) { if (substr($icecat_index_file, -3) == 'zip') { if (!$this->unpackIcecat($icecat_index_file, CSVIPATH_TMP)) { $this->log->addStats('incorrect', 'COM_CSVI_ICECAT_INDEX_NOT_UNPACKED', 'maintenance'); return false; } else { $icecat_index_file = CSVIPATH_TMP . '/icecat_index'; } } $session->set('icecat_index_file', serialize($icecat_index_file), 'com_csvi'); } if ($load_supplier) { if (substr($icecat_supplier_file, -3) == 'zip') { if (!$this->unpackIcecat($icecat_supplier_file, CSVIPATH_TMP)) { $this->log->addStats('incorrect', 'COM_CSVI_ICECAT_SUPPLIER_NOT_UNPACKED', 'maintenance'); return false; } else { $icecat_supplier_file = CSVIPATH_TMP . '/icecat_supplier'; } } $session->set('icecat_supplier_file', serialize($icecat_supplier_file), 'com_csvi'); } } else { $this->log->addStats('incorrect', 'COM_CSVI_ICECAT_NO_USER_PASS', 'maintenance'); return false; } return true; } /** * Load the ICEcat indexes. * * @param FOFInput $input The input model * @param mixed $key A reference used by the method. * * @return bool True on success | False on failure. * * @since 6.0 */ public function icecatIndex(FOFInput $input, $key) { if ($key > 0) { $result = $this->indexIcecat($input, $key); } else { $linenumber = $this->log->getLineNumber(); // Load the index files $session = JFactory::getSession(); $icecat_index_file = unserialize($session->get('icecat_index_file', '', 'com_csvi')); $icecat_supplier_file = unserialize($session->get('icecat_supplier_file', '', 'com_csvi')); // Should we load the index file in 1 go $loadtype = $input->get('loadtype', true, 'bool'); // Check which files to load $icecat_options = $input->get('icecat', array(), null); $icecat_records = $input->get('icecat_records', 1000, 'int'); $session->set('icecat_records', serialize($icecat_records), 'com_csvi'); if (in_array('icecat_index', $icecat_options)) { $load_index = true; } else { $load_index = false; } if (in_array('icecat_supplier', $icecat_options)) { $load_supplier = true; } else { $load_supplier = false; } // First load the supplier file, it is small and easy to do if ($linenumber == 0 && $load_supplier && $icecat_supplier_file) { // Add the line number $this->log->setLinenumber(++$linenumber); // Empty the supplier table $this->db->truncateTable('#__csvi_icecat_suppliers'); // Reset the supplier file $xmlstr = file_get_contents($icecat_supplier_file); $xml = new SimpleXMLElement($xmlstr); $supplier_data = array(); foreach ($xml->SupplierMappings->children() as $mapping) { foreach ($mapping->attributes() as $attr_name => $attr_value) { switch($attr_name) { case 'supplier_id': $supplier_id = $attr_value; break; case 'name': $supplier_data[] = '(' . $this->db->quote($supplier_id) . ',' . $this->db->quote($attr_value) . ')'; } } foreach ($mapping->children() as $symbol) { $supplier_data[] = '(' . $this->db->quote($supplier_id) . ',' . $this->db->quote($symbol) . ')'; } } $q = "INSERT IGNORE INTO ".$this->db->quoteName('#__csvi_icecat_suppliers') . " VALUES " . implode(',', $supplier_data); $this->db->setQuery($q); if ($this->db->execute()) { $input->set('linesprocessed', $this->db->getAffectedRows()); $this->log->addStats('added', 'COM_CSVI_ICECAT_SUPPLIERS_LOADED'); } else { $this->log->addStats('incorrect', JText::sprintf('COM_CSVI_ICECAT_SUPPLIERS_NOT_LOADED', $this->db->getErrorMsg())); } } if (!$loadtype && $load_index) { if ($icecat_index_file) { // Empty the index table $this->db->truncateTable('#__csvi_icecat_index'); // Load the files using INFILE $q = "LOAD DATA LOCAL INFILE " . $this->db->quote($icecat_index_file) . " INTO TABLE " . $this->db->quoteName('#__csvi_icecat_index') . " FIELDS TERMINATED BY '\t' ENCLOSED BY '\"' IGNORE 1 LINES"; $this->db->setQuery($q); // Add the line number $this->log->setLinenumber(++$linenumber); if ($result = $this->db->execute()) { $input->set('linesprocessed', $input->get('linesprocessed') + $this->db->getAffectedRows()); $this->log->addStats('added', 'COM_CSVI_ICECAT_INDEX_LOADED'); } else { $this->log->addStats('incorrect', JText::sprintf('COM_CSVI_ICECAT_INDEX_NOT_LOADED', $this->db->getErrorMsg())); } } else { $this->log->addStats('incorrect', 'COM_CSVI_ICECAT_INDEX_FILE_NOT_FOUND'); } } else { // Check if we are running a cron job list($isCli, $isAdmin) = FOFDispatcher::isCliAdmin(); // Load the files in 1 go using cron if ($isCli) { $continue = true; while ($continue) { $result = $this->indexIcecat($input, $key); $continue = $input->get('continue'); } } // Load the files in steps using gui else { if ($key == 0) { // Empty the index table $this->db->truncateTable('#__csvi_icecat_index'); } $result = $this->indexIcecat($input, $key); } } } return $result; } /** * Post processing index ICEcat. * * @return array Settings for continuing. * * @since 6.0 */ public function onAftericecatIndex() { if ($this->key) { // Return data $results = array(); $results['continue'] = true; $results['key'] = $this->key; } else { $results['continue'] = false; } $results['info'] = $this->message; return $results; } /** * Unpack the ICEcat index files. * * @param string $archivename The full path and name of the file to extract * @param string $extractdir The folder to copy the extracted file to * * @return bool True on success | False on failure. * * @since 3.0 */ private function unpackIcecat($archivename, $extractdir) { $adapter = JArchive::getAdapter('gzip'); if ($adapter) { $config = JFactory::getConfig(); $tmpfname = $config->get('tmp_path') . '/' . uniqid('gzip'); $gzresult = $adapter->extract($archivename, $tmpfname); if (JError::isError($gzresult)) { @unlink($tmpfname); return false; } $path = JPath::clean($extractdir); JFolder::create($path); JFile::copy($tmpfname, $path . '/' . JFile::stripExt(basename(strtolower($archivename)))); @unlink($tmpfname); } return true; } /** * Load the ICEcat index in batches. * * @param FOFInput $input The input model * @param mixed $key A reference used by the method. * * @return bool True on success | False on failure. * * @since 3.3 */ private function indexIcecat(FOFInput $input, $key) { $linenumber = $this->log->getLineNumber(); // Session init $session = JFactory::getSession(); $icecat_index_file = unserialize($session->get('icecat_index_file', '', 'com_csvi')); $records = unserialize($session->get('icecat_records', '', 'com_csvi')); $finished = false; $continue = true; if ($icecat_index_file) { // Sleep to please the server sleep($input->get('icecat_wait', 5)); // Load the records line by line $query = $this->db->getQuery(true) ->insert($this->db->quoteName('#__csvi_icecat_index')) ->columns( $this->db->quoteName('path') . ',' . $this->db->quoteName('product_id') . ',' . $this->db->quoteName('updated') . ',' . $this->db->quoteName('quality') . ',' . $this->db->quoteName('supplier_id') . ',' . $this->db->quoteName('prod_id') . ',' . $this->db->quoteName('catid') . ',' . $this->db->quoteName('m_prod_id') . ',' . $this->db->quoteName('ean_upc') . ',' . $this->db->quoteName('on_market') . ',' . $this->db->quoteName('country_market') . ',' . $this->db->quoteName('model_name') . ',' . $this->db->quoteName('product_view') . ',' . $this->db->quoteName('high_pic') . ',' . $this->db->quoteName('high_pic_size') . ',' . $this->db->quoteName('high_pic_width') . ',' . $this->db->quoteName('high_pic_height') . ',' . $this->db->quoteName('m_supplier_id') . ',' . $this->db->quoteName('m_supplier_name') ); if (($handle = fopen($icecat_index_file, "r")) !== false) { // Position pointers $row = 0; // Position file pointer fseek($handle, $key); // Start processing while ($continue) { if ($row < $records) { $data = fgetcsv($handle, 2048, "\t"); if ($data) { $row++; $lines = array(); foreach ($data as $item) { if (empty($item)) { $lines[] = 'NULL'; } else { $lines[] = $this->db->quote($item); } } $query->values(implode(',', $lines)); } else { $finished = true; $continue = false; } } else { $continue = false; } } // Store the data $this->db->setQuery($query); if ($this->db->execute()) { $this->log->setLineNumber(++$linenumber); $this->log->addStats('added', 'COM_CSVI_ICECAT_INDEX_LOADED'); // Store for future use if (!$finished) { $this->key = ftell($handle); $this->message = JText::sprintf('COM_CSVI_PROCESS_LINES', $row); } else { $this->log->addStats('added', 'COM_CSVI_ICECAT_INDEX_LOADED'); // Clear the session $session->clear('icecat_index_file', 'com_csvi'); $session->clear('icecat_supplier_file', 'com_csvi'); $session->clear('icecat_records', 'com_csvi'); $session->clear('form', 'com_csvi'); } $result = true; } else { $result = false; } fclose($handle); return $result; } else { return false; } } else { return false; } } /** * Clean up because the user has cancelled the operation. * * @return bool Returns true. * * @since 6.0 */ public function cancelOperation() { // Clean the session $session = JFactory::getSession(); $session->clear('icecat_index_file', 'com_csvi'); $session->clear('icecat_supplier_file', 'com_csvi'); return true; } /** * Delete the CSVI tables. * * @return bool Returns true. * * @since 6.0 */ public function deleteTables() { $tables = array( 'csvi_availablefields', 'csvi_availabletables', 'csvi_currency', 'csvi_icecat_index', 'csvi_icecat_suppliers', 'csvi_logdetails', 'csvi_logs', 'csvi_mapheaders', 'csvi_maps', 'csvi_processed', 'csvi_related_categories', 'csvi_related_products', 'csvi_rules', 'csvi_processes', 'csvi_settings', 'csvi_tasks', 'csvi_templatefields', 'csvi_templatefields_rules', 'csvi_templates', 'csvi_template_fields_combine', 'csvi_template_fields_replacement' ); foreach ($tables as $tablename) { $this->db->dropTable($this->db->getPrefix() . $tablename); } return true; } /** * Post process table deletion. * * @return bool Returns true. * * @since 6.0 */ public function onAfterDeleteTables() { // Store the message to show $this->csvihelper->enqueueMessage(JText::_('COM_CSVI_ALL_TABLES_DELETED')); // Since we have no tables left and user plans to uninstall, we need to redirect to the extension manager $cancel = array('url' => 'index.php?option=com_installer&view=manage'); JFactory::getApplication()->input->set('canceloptions', $cancel); return array('cancel' => true); } /** * Install any available example template. * * @param FOFInput $input The input model * * @return bool True on success | false on failure. * * @since 6.4.0 */ public function exampleTemplates(FOFInput $input) { // Get a list of example templates to install $components = $this->csvihelper->getComponents(); jimport('joomla.filesystem.file'); foreach ($components as $component) { // Process all extra available fields $filename = JPATH_ADMINISTRATOR . '/components/com_csvi/addon/' . $component->value . '/install/templates.xml'; if (JFile::exists($filename)) { // Check if the component is installed if (substr($component->value, 0, 4) == 'com_') { $query = $this->db->getQuery(true) ->select($this->db->quoteName('extension_id')) ->from($this->db->quoteName('#__extensions')) ->where($this->db->quoteName('element') . ' = ' . $this->db->quote($component->value)); $this->db->setQuery($query); $ext_id = $this->db->loadResult(); } else { $ext_id = true; } if ($ext_id) { $this->log->add('Processing template file ' . $filename); // Install the templates if ($this->restoreTemplates($input, 0, $filename)) { $this->log->addStats('added', JText::sprintf('COM_CSVI_ADDED_EXAMPLE_TEMPLATEFILE', JText::_('COM_CSVI_' . $component->value))); } } } } } /** * Create available fields table. * * @return bool Returns true. * * @since 6.5.0 */ private function createAvailableFieldsTable() { $query = "CREATE TABLE IF NOT EXISTS `#__csvi_availablefields` ( `csvi_availablefield_id` INT(11) NOT NULL AUTO_INCREMENT, `csvi_name` VARCHAR(255) NOT NULL, `component_name` VARCHAR(55) NOT NULL, `component_table` VARCHAR(55) NOT NULL, `component` VARCHAR(55) NOT NULL, `action` VARCHAR(6) NOT NULL, `isprimary` TINYINT(1) NOT NULL DEFAULT '0', PRIMARY KEY (`csvi_availablefield_id`), UNIQUE INDEX `component_name_table` (`component_name`, `component_table`, `component`, `action`) ) CHARSET=utf8 COMMENT='Available fields for CSVI'"; $this->db->setQuery($query); try { $this->db->execute(); $this->log->addStats('created', 'COM_CSVI_AVAILABLE_FIELDS_TABLE_CREATED', 'availablefields'); } catch (Exception $e) { $this->log->addStats('error', $e->getMessage(), 'availablefields'); return false; } return true; } /** * Post processing of backup templates. * * @return array Settings for continuing. * * @since 6.6.0 */ public function onAfterBackupTemplates() { return array('downloadfile' => $this->downloadfile); } }