Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
wp-content
/
plugins
/
vikbooking
/
admin
/
controllers
:
sampledata.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php /** * @package VikBooking * @subpackage core * @author E4J s.r.l. * @copyright Copyright (C) 2019 E4J s.r.l. All Rights Reserved. * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL * @link https://vikwp.com */ // No direct access defined('ABSPATH') or die('No script kiddies please!'); JLoader::import('adapter.mvc.controllers.admin'); /** * VikBooking Sampledata controller. * * @since 1.3.9 * @see JControllerAdmin */ class VikBookingControllerSampledata extends JControllerAdmin { /** * AJAX endpoint to load the sample data available. * JSON encoded string outputted upon result. * * @return void */ public function load() { $data = $this->getSampleData(); echo json_encode($data); exit; } /** * AJAX endpoint to install one sample data ID. * JSON encoded result outputted or exception thrown. * * @return void * * @throws Exception */ public function install() { $sample_data_id = VikRequest::getInt('sample_data_id', 0, 'request'); if (empty($sample_data_id)) { throw new Exception('Empty Sample Data ID', 500); } // load all sample data available $data = $this->getSampleData(); $sample_data_obj = null; foreach ($data as $sdata) { if (!is_object($sdata) || empty($sdata->id)) { continue; } if ((int)$sdata->id == $sample_data_id) { $sample_data_obj = new JRegistry($sdata); break; } } if (!$sample_data_obj) { throw new Exception(sprintf('Sample Data ID [%s] not found', $sample_data_id), 404); } // response object $response = new stdClass; $response->status = 0; $response->error = ''; // download and install selected sample data try { $res = $this->downloadSampleData($sample_data_obj); if ($res) { $response->status = 1; } } catch (Exception $e) { $response->error = $e->getMessage(); } if ($response->status) { // silently add shortcodes to new WordPress pages $this->addShortcodesToPages($sample_data_obj); } echo json_encode($response); exit; } /** * Returns a list of supported sample data. * * @return array A list of sample data. */ private function getSampleData() { // build transient key $transient = 'vikbooking_sampledata_' . md5(VIKBOOKING_SOFTWARE_VERSION); // get cached sample data list $data = get_transient($transient); if ($data) { // return cached transient $data = json_decode($data); return is_array($data) ? $data : array(); } // default empty list $data = array(); // instantiate HTTP transport $http = new JHttp(); // build end-point URI $uri = 'https://vikwp.com/api/?task=sampledata.list'; // build post data $post = array( 'sku' => 'vbo', 'version' => VIKBOOKING_SOFTWARE_VERSION, ); // load sample data from server $response = $http->post($uri, $post); if ($response->code == 200) { // decode response $data = json_decode($response->body); // cache sample data list for an hour set_transient($transient, json_encode($data), HOUR_IN_SECONDS); } return $data; } /** * Downloads and installs one sample data. * * @param JRegistry $data The sample data registry object. * * @return boolean * * @uses installSampleData() */ private function downloadSampleData($data) { // instantiate HTTP transport $http = new JHttp(); // get selected sample data $id = $data->get('id'); JLoader::import('adapter.filesystem.folder'); // get temporary dir $tmp = get_temp_dir(); // clean temporary path $tmp = rtrim(JPath::clean($tmp), DIRECTORY_SEPARATOR); // make sure the folder exists if (!is_dir($tmp)) { throw new Exception(sprintf('Temporary folder [%s] does not exist', $tmp), 404); } // make sure the temporary folder is writable if (!wp_is_writable($tmp)) { throw new Exception(sprintf('Temporary folder [%s] is not writable', $tmp), 403); } // download end-point $url = 'https://vikwp.com/api/?task=sampledata.download'; // init HTTP transport $http = new JHttp(); // build sample data file name $packname = 'sampledata-' . uniqid(); // build request headers $headers = array( // turn on stream to push body within a file 'stream' => true, // define the filepath in which the data will be pushed 'filename' => $tmp . DIRECTORY_SEPARATOR . $packname . '.zip', // make sure the request is non blocking 'blocking' => true, // force timeout to 60 seconds 'timeout' => 60, ); // build post data $body = array( 'id' => $id, ); // make connection with VikWP server $response = $http->post($url, $body, $headers); if ($response->code != 200) { // raise error returned by VikWP throw new Exception($response->body, $response->code); } // make sure the file has been saved if (!JFile::exists($headers['filename'])) { throw new Exception('ZIP package could not be saved on disk', 404); } // create destination folder for extracted elements $dest = $tmp . DIRECTORY_SEPARATOR . $packname; // make sure the destination folder doesn't exist if (JFolder::exists($dest)) { // remove it before proceeding with the extraction JFolder::delete($dest); } // import archive class handler JLoader::import('adapter.filesystem.archive'); // the package was downloaded successfully, let's extract it (onto TMP folder) $extracted = JArchive::extract($headers['filename'], $dest); // we no longer need the archive JFile::delete($headers['filename']); if (!$extracted) { // an error occurred while extracting the files throw new Exception(sprintf('Cannot extract files to [%s]', $tmp), 500); } // make sure the folder is intact if (!JFolder::exists($dest)) { // impossible to access the extracted elements throw new Exception(sprintf('Cannot access extracted elements from [%s] folder', $dest), 404); } $error = null; try { // run sample data installation $this->installSampleData($dest); } catch (Exception $e) { // safely catch error to finalize process $error = $e; } // process complete, clean up the temporary folder before exiting JFolder::delete($dest); // in case of error, propagate it after deleting the extracted folder if ($error) { throw $error; } return true; } /** * Interprets the manifest contained within the folder * to install the sample data. * * @param string $folder The sample data folder. * * @return void * * @throws Exception * * @uses uninstallShortcodes() * @uses installSqlRole() * @uses installFilesRole() */ private function installSampleData($folder) { // load manifest.json file if (!is_file($folder . DIRECTORY_SEPARATOR . 'manifest.json')) { // missing JSON manifest throw new Exception('Manifest file not found', 404); } // open manifest file in read mode $manifestFile = fopen($folder . DIRECTORY_SEPARATOR . 'manifest.json', 'r'); $manifest = ''; // load manifest content while (!feof($manifestFile)) { $manifest .= fread($manifestFile, 8192); } // close file fclose($manifestFile); // decode JSON $manifest = json_decode($manifest); if (!$manifest) { // unable to JSON decode manifest throw new Exception('Manifest file contains an invalid JSON', 500); } $dbo = JFactory::getDbo(); // look for uninstall queries if (isset($manifest->uninstall)) { // iterate queries to clean any existing records foreach ($manifest->uninstall as $q) { try { // check if we are uninstalling the shortcodes if (preg_match("/vikbooking_wpshortcodes/i", $q)) { // uninstall the existing shortcodes $this->uninstallShortcodes(); } // launch query $dbo->setQuery($q); $dbo->execute(); } catch (Exception $e) { // malformed query, suppress error and go ahead if (VIKBOOKING_DEBUG) { // propagate error in case of debug mode enabled throw $e; } } } } // look for installers if (isset($manifest->installers)) { // iterate installers foreach ($manifest->installers as $install) { try { // switch case role to invoke the proper installation method switch ($install->role) { case 'sql': case 'insert': $this->installSqlRole($install->data); break; case 'media': case 'folder': $this->installFilesRole($install->data->destination, $install->data->files, $folder); break; } } catch (Exception $e) { // malformed role, suppress error and go ahead if (VIKBOOKING_DEBUG) { // propagate error in case of debug mode enabled throw $e; } } } } } /** * Executes the specified queries. * * @param mixed $queries Either a query string or an array. * * @return void */ private function installSqlRole($queries) { if (!is_array($queries)) { $queries = array($queries); } $dbo = JFactory::getDbo(); // iterate queries one by one foreach ($queries as $q) { $dbo->setQuery($q); $dbo->execute(); } } /** * Moves the files into the related folders. * * @param string $dest The destination folder. * @param mixed $files Either a file or an array. * @param string $dir The current directory. * * @return void */ private function installFilesRole($dest, $files, $dir) { // load update manager class for backup/mirroring of files VikBookingLoader::import('update.manager'); // set destination by prepending plugin base path $dest = VIKBOOKING_BASE . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $dest); // make sure to always parse an array if (!is_array($files)) { $files = array($files); } // copy files and create a backup copy from each file foreach ($files as $file) { // fetch file path $path = JPath::clean($dir . DIRECTORY_SEPARATOR . $file); // fetch destination file path $destFile = JPath::clean($dest . DIRECTORY_SEPARATOR . basename($file)); // copy file in its destination $res = JFile::copy($path, $destFile); if ($res) { // trigger mirroring action for new file uploaded VikBookingUpdateManager::triggerUploadBackup($destFile); } } } /** * Uninstalls all the pages that have been assigned * to the existing shortcodes. * * @return void */ private function uninstallShortcodes() { // get shortcode admin model $model = JModel::getInstance('vikbooking', 'shortcodes'); // get all existing shortcodes $shortcodes = $model->all(array('createdon', 'post_id')); // iterate all shortcodes found foreach ($shortcodes as $shortcode) { // make sure the shortcode has been assigned to a post if ($shortcode->post_id) { // get post details $post = get_post((int) $shortcode->post_id); // convert shortcode creation date $shortcode->createdon = new JDate($shortcode->createdon); // convert post creation date $post->post_date_gmt = new JDate($post->post_date_gmt); // compare ephocs and make sure the post was not created before the shortcode if ((int) $shortcode->createdon->format('U') <= (int) $post->post_date_gmt->format('U')) { // permanently delete post wp_delete_post($post->ID, $force_delete = true); } } } } /** * Finalizes the installation of a sample data by creating one * new WordPress page/post for each Shortcode installed. * * @param JRegistry $data The (optional) sample data chosen registry object. * * @return boolean */ private function addShortcodesToPages($data = null) { $model = JModel::getInstance('vikbooking', 'shortcodes'); $shortcodes = $model->all(); if (!is_array($shortcodes) || !count($shortcodes)) { return false; } foreach ($shortcodes as $item) { if (!empty($item->post_id)) { // shortcode already linked to a page continue; } /** * Add a new page (we allow a WP_ERROR to be returned in case of failure). * This should automatically trigger the hook that we use to link the Shortcode * to the new page/post ID, and so there's no need to update the item. */ $new_page_id = wp_insert_post(array( 'post_title' => (!empty($item->name) ? $item->name : JText::translate($item->title)), 'post_content' => $item->shortcode, 'post_status' => 'publish', 'post_type' => 'page', ), true); // we ignore if the page was created or if an error occurred } return true; } }