From 47d1a6c155c0a74b4987fd9ca04afb5933d2433c Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Wed, 25 Apr 2018 00:36:05 +0200 Subject: [PATCH] Added the feature that allows you to setup the behaviour of a selected set of components that will be auto build and installed. So you do not need to manually compile and install those components any more, the system does all that automatically for you. We have called the feature Expansion Development Method, and it can be set in the global settings of JCB under the Development Method tab. --- README.md | 6 +- admin/README.txt | 6 +- admin/config.xml | 33 +- admin/controllers/compiler.php | 2 +- admin/helpers/compiler.php | 4 +- admin/helpers/compiler/a_Get.php | 6 +- admin/helpers/compiler/b_Structure.php | 4 +- admin/helpers/compiler/e_Interpretation.php | 24 +- admin/helpers/compiler/f_Infusion.php | 2 +- admin/helpers/componentbuilder.php | 601 ++++++++++++++++++ .../en-GB/en-GB.com_componentbuilder.ini | 69 +- admin/models/ajax.php | 15 +- admin/models/compiler.php | 22 +- componentbuilder.xml | 2 +- site/controllers/api.php | 134 ++++ site/helpers/componentbuilder.php | 601 ++++++++++++++++++ .../en-GB/en-GB.com_componentbuilder.ini | 6 + site/models/api.php | 70 +- 18 files changed, 1525 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 65b2d5ef8..1b002a182 100644 --- a/README.md +++ b/README.md @@ -126,12 +126,12 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 23rd April, 2018 ++ *Last Build*: 24th April, 2018 + *Version*: 2.7.6 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **184709** -+ *Field count*: **1025** ++ *Line count*: **193223** ++ *Field count*: **1026** + *File count*: **1201** + *Folder count*: **193** diff --git a/admin/README.txt b/admin/README.txt index 65b2d5ef8..1b002a182 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -126,12 +126,12 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 23rd April, 2018 ++ *Last Build*: 24th April, 2018 + *Version*: 2.7.6 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **184709** -+ *Field count*: **1025** ++ *Line count*: **193223** ++ *Field count*: **1026** + *File count*: **1201** + *Folder count*: **193** diff --git a/admin/config.xml b/admin/config.xml index 8dc88dc04..acedbd074 100644 --- a/admin/config.xml +++ b/admin/config.xml @@ -653,33 +653,24 @@ description="COM_COMPONENTBUILDER_CONFIG_REPOSITORY_DESCRIPTION" class="inputbox" /> - + - - - - - - - + description="COM_COMPONENTBUILDER_CONFIG_PLACEHOLDERS_DESCRIPTION" + class="inputbox" + /> + +
+ name="auto_backup_custom_config" + label="COM_COMPONENTBUILDER_CONFIG_AUTO_BACKUP"> diff --git a/admin/controllers/compiler.php b/admin/controllers/compiler.php index 445d35742..5da805b60 100644 --- a/admin/controllers/compiler.php +++ b/admin/controllers/compiler.php @@ -194,7 +194,7 @@ class ComponentbuilderControllerCompiler extends JControllerAdmin $lang->load($extension, $base_dir, $language_tag, $reload); $message = '('.$fileName.'.zip) file was also removed from tmp!'; $this->setRedirect($redirect_url,$message,'message'); - return $model->install($fileName.'.zip');; + return $model->install($fileName.'.zip'); } } $this->setRedirect($redirect_url,$message,'error'); diff --git a/admin/helpers/compiler.php b/admin/helpers/compiler.php index 6a58752f6..0aa5b18b2 100644 --- a/admin/helpers/compiler.php +++ b/admin/helpers/compiler.php @@ -72,12 +72,12 @@ class Compiler extends Infusion $comConfig = JFactory::getConfig(); $this->tempPath = $comConfig->get('tmp_path'); // set some folder paths in relation to distribution - if ($config['addBackup']) + if ($config['backup']) { $this->backupPath = $this->params->get('backup_folder_path', $this->tempPath) . '/' . $this->componentBackupName . '.zip'; $this->dynamicIntegration = true; } - if ($config['addRepo']) + if ($config['repository']) { $this->repoPath = $this->params->get('git_folder_path', null); } diff --git a/admin/helpers/compiler/a_Get.php b/admin/helpers/compiler/a_Get.php index d11230710..add968cbf 100644 --- a/admin/helpers/compiler/a_Get.php +++ b/admin/helpers/compiler/a_Get.php @@ -668,7 +668,7 @@ class Get // load the compiler path $this->compilerPath = $this->params->get('compiler_folder_path', JPATH_COMPONENT_ADMINISTRATOR . '/compiler'); // set the component ID - $this->componentID = (int) $config['componentId']; + $this->componentID = (int) $config['component']; // set this components code name if ($name_code = ComponentbuilderHelper::getVar('joomla_component', $this->componentID, 'id', 'name_code')) { @@ -678,10 +678,10 @@ class Get $this->componentCodeName = ComponentbuilderHelper::safeString($name_code); // set if placeholders should be added to customcode $global = ((int) ComponentbuilderHelper::getVar('joomla_component', $this->componentID, 'id', 'add_placeholders') == 1) ? true : false; - $this->addPlaceholders = ((int) $config['addPlaceholders'] == 0) ? false : (((int) $config['addPlaceholders'] == 1) ? true : $global); + $this->addPlaceholders = ((int) $config['placeholders'] == 0) ? false : (((int) $config['placeholders'] == 1) ? true : $global); // set if line numbers should be added to comments $global = ((int) ComponentbuilderHelper::getVar('joomla_component', $this->componentID, 'id', 'debug_linenr') == 1) ? true : false; - $this->debugLinenr = ((int) $config['debugLinenr'] == 0) ? false : (((int) $config['debugLinenr'] == 1) ? true : $global); + $this->debugLinenr = ((int) $config['debuglinenr'] == 0) ? false : (((int) $config['debuglinenr'] == 1) ? true : $global); // set the current user $this->user = JFactory::getUser(); // Get a db connection. diff --git a/admin/helpers/compiler/b_Structure.php b/admin/helpers/compiler/b_Structure.php index 5dd4a69ea..acc8df02a 100644 --- a/admin/helpers/compiler/b_Structure.php +++ b/admin/helpers/compiler/b_Structure.php @@ -338,9 +338,9 @@ class Structure extends Get // run global updater ComponentbuilderHelper::runGlobalUpdater(); // set the Joomla version - $this->joomlaVersion = $config['joomlaVersion']; + $this->joomlaVersion = $config['version']; // set the template path - $this->templatePath = $this->compilerPath . '/joomla_' . $config['joomlaVersion']; + $this->templatePath = $this->compilerPath . '/joomla_' . $config['version']; // set some default names $this->componentSalesName = 'com_' . $this->componentData->sales_name . '__J' . $this->joomlaVersion; $this->componentBackupName = 'com_' . $this->componentData->sales_name . '_v' . str_replace('.', '_', $this->componentData->component_version) . '__J' . $this->joomlaVersion; diff --git a/admin/helpers/compiler/e_Interpretation.php b/admin/helpers/compiler/e_Interpretation.php index 4ae4c32a7..0776a654d 100644 --- a/admin/helpers/compiler/e_Interpretation.php +++ b/admin/helpers/compiler/e_Interpretation.php @@ -13048,12 +13048,6 @@ class Interpretation extends Fields $tabCode = ComponentbuilderHelper::safeString($tab) . '_custom_config'; $tabUpper = ComponentbuilderHelper::safeString($tab, 'U'); $tabLower = ComponentbuilderHelper::safeString($tab); - // setup lang - $this->langContent[$this->lang][$lang . '_' . $tabUpper] = $tab; - // start field set - $this->configFieldSets[] = "\tconfigFieldSets[] = "\t\t" . 'name="' . $tabCode . '"'; - $this->configFieldSets[] = "\t\t" . 'label="' . $lang . '_' . $tabUpper . '">'; // remove display targeted fields $bucket = array(); foreach ($tabFields as $tabField) @@ -13065,10 +13059,20 @@ class Interpretation extends Fields $bucket[] = str_replace('display="config"', '', $tabField); } } - // set the fields - $this->configFieldSets[] = implode("", $bucket); - // close field set - $this->configFieldSets[] = "\t
"; + // only add the tab if it has values + if (ComponentbuilderHelper::checkArray($bucket)) + { + // setup lang + $this->langContent[$this->lang][$lang . '_' . $tabUpper] = $tab; + // start field set + $this->configFieldSets[] = "\tconfigFieldSets[] = "\t\t" . 'name="' . $tabCode . '"'; + $this->configFieldSets[] = "\t\t" . 'label="' . $lang . '_' . $tabUpper . '">'; + // set the fields + $this->configFieldSets[] = implode("", $bucket); + // close field set + $this->configFieldSets[] = "\t"; + } // remove after loading unset($this->configFieldSetsCustomField[$tab]); } diff --git a/admin/helpers/compiler/f_Infusion.php b/admin/helpers/compiler/f_Infusion.php index a5bfa1b87..53a43be1a 100644 --- a/admin/helpers/compiler/f_Infusion.php +++ b/admin/helpers/compiler/f_Infusion.php @@ -1175,7 +1175,7 @@ class Infusion extends Interpretation // add to language file $this->writeFile($path . '/' . $fileName, implode(PHP_EOL, $lang)); // set the line counter - $this->lineCount = $this->lineCount + substr_count($lang, PHP_EOL); + $this->lineCount = $this->lineCount + count((array)$lang); // build xml strings if (!isset($langXML[$p])) { diff --git a/admin/helpers/componentbuilder.php b/admin/helpers/componentbuilder.php index fc47d736c..1825d5d0b 100644 --- a/admin/helpers/componentbuilder.php +++ b/admin/helpers/componentbuilder.php @@ -2290,6 +2290,607 @@ abstract class ComponentbuilderHelper } } + /** + * the locker + * + * @var array + **/ + protected static $locker = array(); + + /** + * the dynamic replacement salt + * + * @var array + **/ + protected static $globalSalt = array(); + + /** + * the timer + * + * @var object + **/ + protected static $keytimer; + + /** + * To Lock string + * + * @param string $string The string/array to lock + * @param string $key The custom key to use + * @param int $salt The switch to add salt and type of salt + * @param int $dynamic The dynamic replacement array of salt build string + * @param int $urlencode The switch to control url encoding + **/ + public static function lock($string, $key = null, $salt = 2, $dynamic = null, $urlencode = true) + { + // get the global settings + if (!$key || !self::checkString($key)) + { + // set temp timer + $timer = 2; + // if we have a timer use it + if ($salt > 0) + { + $timer = $salt; + } + if (method_exists(get_called_class(), "getCryptKey")) + { + $key = self::getCryptKey('basic', self::salt($timer, $dynamic)); + } + else + { + $key = self::salt($timer, $dynamic); + } + } + // check if we have a salt timer + if ($salt > 0) + { + $key .= self::salt($salt, $dynamic); + } + // get the locker settings + if (!isset(self::$locker[$key]) || !self::checkObject(self::$locker[$key])) + { + self::$locker[$key] = new FOFEncryptAes($key, 128); + } + // convert array or object to string + if (self::checkArray($string) || self::checkObject($string)) + { + $string = serialize($string); + } + // prep for url + if ($urlencode) + { + return self::base64_urlencode(self::$locker[$key]->encryptString($string)); + } + return self::$locker[$key]->encryptString($string); + } + + /** + * To un-Lock string + * + * @param string $string The string to unlock + * @param string $key The custom key to use + * @param int $salt The switch to add salt and type of salt + * @param int $dynamic The dynamic replacement array of salt build string + * @param int $urlencode The switch to control url decoding + **/ + public static function unlock($string, $key = null, $salt = 2, $dynamic = null, $urlencode = true) + { + // get the global settings + if (!$key || !self::checkString($key)) + { + // set temp timer + $timer = 2; + // if we have a timer use it + if ($salt > 0) + { + $timer = $salt; + } + // get secure key + if (method_exists(get_called_class(), "getCryptKey")) + { + $key = self::getCryptKey('basic', self::salt($timer, $dynamic)); + } + else + { + $key = self::salt($timer, $dynamic); + } + } + // check if we have a salt timer + if ($salt > 0) + { + $key .= self::salt($salt, $dynamic); + } + // get the locker settings + if (!isset(self::$locker[$key]) || !self::checkObject(self::$locker[$key])) + { + self::$locker[$key] = new FOFEncryptAes($key, 128); + } + // make sure we have real base64 + if ($urlencode) + { + $string = self::base64_urldecode($string); + } + // basic decrypt string. + if (!empty($string) && !is_numeric($string) && $string === base64_encode(base64_decode($string, true))) + { + $string = rtrim(self::$locker[$key]->decryptString($string), "\0"); + // convert serial string to array + if (self::is_serial($string)) + { + $string = unserialize($string); + } + } + return $string; + } + + /** + * The Salt + * + * @param int $type The type of length the salt should be valid + * @param int $dynamic The dynamic replacement array of salt build string + **/ + public static function salt($type = 1, $dynamic = null) + { + // get dynamic replacement salt + $dynamic = self::getDynamicSalt($dynamic); + // get the key timer + if (!self::checkObject(self::$keytimer)) + { + // load the date time object + self::$keytimer = new DateTime; + // set the correct time stamp + $vdmLocalTime = new DateTimeZone('Africa/Windhoek'); + self::$keytimer->setTimezone($vdmLocalTime); + } + // set type + if ($type == 2) + { + // hour + $format = 'Y-m-d \o\n ' . self::periodFix(self::$keytimer->format('H')); + } + elseif ($type == 3) + { + // day + $format = 'Y-m-' . self::periodFix(self::$keytimer->format('d')); + } + elseif ($type == 4) + { + // month + $format = 'Y-' . self::periodFix(self::$keytimer->format('m')); + } + else + { + // minute + $format = 'Y-m-d \o\n H:' . self::periodFix(self::$keytimer->format('i')); + } + // get key + if (self::checkArray($dynamic)) + { + return md5(str_replace(array_keys($dynamic), array_values($dynamic), self::$keytimer->format($format) . ' @ VDM.I0')); + } + return md5(self::$keytimer->format($format) . ' @ VDM.I0'); + } + + /** + * The function to insure the salt is valid within the given period (third try) + * + * @param int $main The main number + */ + protected static function periodFix($main) + { + return round($main / 3) * 3; + } + + /** + * Check if a string is serialized + * @param string $string + */ + public static function is_serial($string) + { + return (@unserialize($string) !== false); + } + + /** + * Get dynamic replacement salt + */ + public static function getDynamicSalt($dynamic = null) + { + // load global if not manually set + if (!self::checkArray($dynamic)) + { + return self::getGlobalSalt(); + } + // return manual values if set + else + { + return $dynamic; + } + } + + /** + * The random or dynamic secret salt + */ + public static function getSecretSalt($string = null, $size = 9) + { + // set the string + if (!$string) + { + // get random string + $string = self::randomkey($size); + } + // convert string to array + $string = self::safeString($string); + // convert string to array + $array = str_split($string); + // insure only unique values are used + $array = array_unique($array); + // set the size + $size = ($size <= count($array)) ? $size : count($array); + // down size the + return array_slice($array, 0, $size); + } + + /** + * Get global replacement salt + */ + public static function getGlobalSalt() + { + // load from memory if found + if (!self::checkArray(self::$globalSalt)) + { + // get the global settings + if (!self::checkObject(self::$params)) + { + self::$params = JComponentHelper::getParams('com_componentbuilder'); + } + // check if we have a global dynamic replacement array available (format --> ' 1->!,3->E,4->A') + $tmp = self::$params->get('dynamic_salt', null); + if (self::checkString($tmp) && strpos($tmp, ',') !== false && strpos($tmp, '->') !== false) + { + $salt = array_map('trim', (array) explode(',', $tmp)); + if (self::checkArray($salt )) + { + foreach($salt as $replace) + { + $dynamic = array_map('trim', (array) explode('->', $replace)); + if (isset($dynamic[0]) && isset($dynamic[1])) + { + self::$globalSalt[$dynamic[0]] = $dynamic[1]; + } + } + } + } + } + // return global if found + if (self::checkArray(self::$globalSalt)) + { + return self::$globalSalt; + } + // return default as fail safe + return array('1' => '!', '3' => 'E', '4' => 'A'); + } + + /** + * Close public protocol + */ + public static function closePublicProtocol($id, $public) + { + // get secret salt + $secretSalt = self::getSecretSalt(self::salt(1,array('4' => 'R','1' => 'E','2' => 'G','7' => 'J','8' => 'A'))); + // get the key + $key = self::salt(1, $secretSalt); + // get secret salt + $secret = self::getSecretSalt(); + // set the secret + $close['SECRET'] = self::lock($secret, $key, 1, array('1' => 's', '3' => 'R', '4' => 'D')); + // get the key + $key = self::salt(1, $secret); + // get the public key + $close['PUBLIC'] = self::lock($public, $key, 1, array('1' => '!', '3' => 'E', '4' => 'A')); + // get secret salt + $secretSalt = self::getSecretSalt($public); + // get the key + $key = self::salt(1, $secretSalt); + // get the ID + $close['ID'] = self::unlock($id, $key, 1, array('1' => 'i', '3' => 'e', '4' => 'B')); + // return closed values + return $close; + } + + /** + * Open public protocol + */ + public static function openPublicProtocol($SECRET, $ID, $PUBLIC) + { + // get secret salt + $secretSalt = self::getSecretSalt(self::salt(1,array('4' => 'R','1' => 'E','2' => 'G','7' => 'J','8' => 'A'))); + // get the key + $key = self::salt(1, $secretSalt); + // get the $SECRET + $SECRET = self::unlock($SECRET, $key, 1, array('1' => 's', '3' => 'R', '4' => 'D')); + // get the key + $key = self::salt(1, $SECRET); + // get the public key + $open['public'] = self::unlock($PUBLIC, $key, 1, array('1' => '!', '3' => 'E', '4' => 'A')); + // get secret salt + $secretSalt = self::getSecretSalt($open['public']); + // get the key + $key = self::salt(1, $secretSalt); + // get the ID + $open['id'] = self::unlock($ID, $key, 1, array('1' => 'i', '3' => 'e', '4' => 'B')); + // return opened values + return $open; + } + + /** + * Workers to load tasks + * + * @var array + */ + protected static $worker = array(); + + /** + * Set a worker dynamic URLs + * + * @var array + */ + protected static $workerURL = array(); + + /** + * Set a worker dynamic HEADERs + * + * @var array + */ + protected static $workerHEADER = array(); + + /** + * Curl Error Notice + * + * @var bool + */ + protected static $curlErrorLoaded = false; + + /** + * Set a worker url + * + * @param string $function The function to target to perform the task + * @param string $url The url of where the task is to be performed + * + * @return void + * + */ + public static function setWorkerUrl(&$function, &$url) + { + // set the URL if found + if (self::checkString($url)) + { + // make sure task function url is up + self::$workerURL[$function] = $url; + } + } + + /** + * Set a worker headers + * + * @param string $function The function to target to perform the task + * @param array $headers The headers needed for these workers/function + * + * @return void + * + */ + public static function setWorkerHeaders(&$function, &$headers) + { + // set the Headers if found + if (self::checkArray($headers)) + { + // make sure task function headers are set + self::$workerHEADER[$function] = $headers; + } + } + + /** + * Set a worker that needs to perform a task + * + * @param mixed $data The data to pass to the task + * @param string $function The function to target to perform the task + * @param string $url The url of where the task is to be performed + * @param array $headers The headers needed for these workers/function + * + * @return void + * + */ + public static function setWorker($data, $function, $url = null, $headers = null) + { + // make sure task function is up + if (!isset(self::$worker[$function])) + { + self::$worker[$function] = array(); + } + // load the task + self::$worker[$function][] = self::lock($data); + // set the Headers if found + if ($headers && !isset(self::$workerHEADER[$function])) + { + self::setWorkerHeaders($function, $headers); + } + // set the URL if found + if ($url && !isset(self::$workerURL[$function])) + { + self::setWorkerUrl($function, $url); + } + } + + /** + * Run set Workers + * + * @param string $function The function to target to perform the task + * @param string $perTask The amount of task per worker + * @param function $callback The option to do a call back when task is completed + * @param int $threadSize The size of the thread + * + * @return bool true On success + * + */ + public static function runWorker($function, $perTask = 50, $callback = null, $threadSize = 20) + { + // set task + $task = self::lock($function); + // build headers + $headers = array('VDM-TASK: ' .$task); + // build dynamic headers + if (isset(self::$workerHEADER[$function]) && self::checkArray(self::$workerHEADER[$function])) + { + foreach (self::$workerHEADER[$function] as $header) + { + $headers[] = $header; + } + } + // build worker options + $options = array(); + // make sure worker is up + if (isset(self::$worker[$function]) && self::checkArray(self::$worker[$function])) + { + // this load method is for each + if (1 == $perTask) + { + // working with a string = 1 + $headers[] = 'VDM-VALUE-TYPE: ' .self::lock(1); + // now load the options + foreach (self::$worker[$function] as $data) + { + $options[] = array(CURLOPT_HTTPHEADER => $headers, CURLOPT_POST => 1, CURLOPT_POSTFIELDS => 'VDM_DATA='. $data); + } + } + // this load method is for bundles + else + { + // working with an array = 2 + $headers[] = 'VDM-VALUE-TYPE: ' .self::lock(2); + // now load the options + $work = array_chunk(self::$worker[$function], $perTask); + foreach ($work as $data) + { + $options[] = array(CURLOPT_HTTPHEADER => $headers, CURLOPT_POST => 1, CURLOPT_POSTFIELDS => 'VDM_DATA='. implode('___VDM___', $data)); + } + } + // relieve worker of task/function + self::$worker[$function] = array(); + } + // do the execution + if (self::checkArray($options)) + { + if (isset(self::$workerURL[$function])) + { + $url = self::$workerURL[$function]; + } + else + { + $url = JURI::root() . '/index.php?option=com_componentbuilder&task=api.worker'; + } + return self::curlMultiExec($url, $options, $callback, $threadSize); + } + return false; + } + + /** + * Do a multi curl execution of tasks + * + * @param string $url The url of where the task is to be performed + * @param array $_options The array of curl options/headers to set + * @param function $callback The option to do a call back when task is completed + * @param int $threadSize The size of the thread + * + * @return bool true On success + * + */ + public static function curlMultiExec(&$url, &$_options, $callback = null, $threadSize = 20) + { + // make sure we have curl available + if (!function_exists('curl_version')) + { + if (!self::$curlErrorLoaded) + { + // set the notice + JFactory::getApplication()->enqueueMessage(JText::_('COM_COMPONENTBUILDER_HTWOCURL_NOT_FOUNDHTWOPPLEASE_SETUP_CURL_ON_YOUR_SYSTEM_OR_BCOMPONENTBUILDERB_WILL_NOT_FUNCTION_CORRECTLYP'), 'Error'); + // load the notice only once + self::$curlErrorLoaded = true; + } + return false; + } + // make sure we have an url + if (self::checkString($url)) + { + // make sure the thread size isn't greater than the # of _options + $threadSize = (count($_options) < $threadSize) ? count($_options) : $threadSize; + // set the options + $options = array(); + $options[CURLOPT_URL] = $url; + $options[CURLOPT_USERAGENT] = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12'; + $options[CURLOPT_RETURNTRANSFER] = TRUE; + $options[CURLOPT_SSL_VERIFYPEER] = FALSE; + // start multi threading :) + $handle = curl_multi_init(); + // start the first batch of requests + for ($i = 0; $i < $threadSize; $i++) + { + if (isset($_options[$i])) + { + $ch = curl_init(); + foreach ($_options[$i] as $curlopt => $string) + { + $options[$curlopt] = $string; + } + curl_setopt_array($ch, $options); + curl_multi_add_handle($handle, $ch); + } + } + // we wait for all the calls to finish (should not take long) + do { + while(($execrun = curl_multi_exec($handle, $working)) == CURLM_CALL_MULTI_PERFORM); + if($execrun != CURLM_OK) + break; + // a request was just completed -- find out which one + while($done = curl_multi_info_read($handle)) + { + if (is_callable($callback)) + { + // $info = curl_getinfo($done['handle']); + // request successful. process output using the callback function. + $output = curl_multi_getcontent($done['handle']); + $callback($output); + } + $key = $i + 1; + if(isset($_options[$key])) + { + // start a new request (it's important to do this before removing the old one) + $ch = curl_init(); $i++; + // add options + foreach ($_options[$key] as $curlopt => $string) + { + $options[$curlopt] = $string; + } + curl_setopt_array($ch, $options); + curl_multi_add_handle($handle, $ch); + // remove options again + foreach ($_options[$key] as $curlopt => $string) + { + unset($options[$curlopt]); + } + } + // remove the curl handle that just completed + curl_multi_remove_handle($handle, $done['handle']); + } + // stop wasting CPU cycles and rest for a couple ms + usleep(10000); + } while ($working); + // close the curl multi thread + curl_multi_close($handle); + // okay done + return true; + } + return false; + } + /** * Move File to Server * diff --git a/admin/language/en-GB/en-GB.com_componentbuilder.ini b/admin/language/en-GB/en-GB.com_componentbuilder.ini index a103fa9c2..d0c324446 100644 --- a/admin/language/en-GB/en-GB.com_componentbuilder.ini +++ b/admin/language/en-GB/en-GB.com_componentbuilder.ini @@ -2041,12 +2041,12 @@ COM_COMPONENTBUILDER_COMPONENT_FILES_FOLDERS_NOTE_CONSTANT_PATHS_DESCRIPTION="

JPATH_BASE
// The path to the cache folder.
JPATH_CACHE
-// The path to the administration folder of the current component being executed.
-JPATH_COMPONENT_ADMINISTRATOR
-// The path to the site folder of the current component being executed.
-JPATH_COMPONENT_SITE
-// The path to the current component being executed.
-JPATH_COMPONENT
+// The path to the administration folder of JCB component.
+JPATH_COMPONENT_ADMINISTRATOR no ideal to use
+// The path to the site folder of JCB component.
+JPATH_COMPONENT_SITE no ideal to use
+// The path to the JCB component.
+JPATH_COMPONENT no ideal to use
// The path to folder containing the configuration.php file.
JPATH_CONFIGURATION
// The path to the installation folder.
@@ -2218,6 +2218,7 @@ COM_COMPONENTBUILDER_CONFIG_AUTHOR_EMAIL_DESC="The email address of the author o COM_COMPONENTBUILDER_CONFIG_AUTHOR_EMAIL_LABEL="Author Email" COM_COMPONENTBUILDER_CONFIG_AUTHOR_NAME_DESC="The name of the author of this component." COM_COMPONENTBUILDER_CONFIG_AUTHOR_NAME_LABEL="Author Name" +COM_COMPONENTBUILDER_CONFIG_AUTO_BACKUP="Auto Backup" COM_COMPONENTBUILDER_CONFIG_AUTO_LOAD="Auto" COM_COMPONENTBUILDER_CONFIG_BACKUPCRONJOB_NOTE_DESCRIPTION="You can run a cronjob that will backup all your components as they are mapped in JCB.

USE THE FOLLOWING: loading...

Please note that if your Joomla website has a Firewall installed, it will not allow cronjob via direct URL (most of the time), you will then need to adapt the cornjob request to look like a browser. For more info please read https://stackoverflow.com/a/31597823/1429677 " COM_COMPONENTBUILDER_CONFIG_BACKUPCRONJOB_NOTE_LABEL="Backup JCB Mapped Components" @@ -2307,7 +2308,6 @@ COM_COMPONENTBUILDER_CONFIG_COMPILER_FOLDER_PATH_LABEL="Compiler Folder Path" COM_COMPONENTBUILDER_CONFIG_COMPILER_FOLDER_PATH_MESSAGE="Error! Please add some text here." COM_COMPONENTBUILDER_CONFIG_COMPONENT="Component" COM_COMPONENTBUILDER_CONFIG_COMPONENT_LABEL="Component" -COM_COMPONENTBUILDER_CONFIG_CRONJOB="CronJob" COM_COMPONENTBUILDER_CONFIG_CRONJOB_BACKUP_FOLDER_PATH_DESCRIPTION="Here you can set the path to where all components are backed up to." COM_COMPONENTBUILDER_CONFIG_CRONJOB_BACKUP_FOLDER_PATH_HINT="/home/user/fullbackup" COM_COMPONENTBUILDER_CONFIG_CRONJOB_BACKUP_FOLDER_PATH_LABEL="Cronjob Backup Folder Path" @@ -2357,7 +2357,6 @@ COM_COMPONENTBUILDER_CONFIG_EMAILREPLY_HINT="Email Address Here" COM_COMPONENTBUILDER_CONFIG_EMAILREPLY_LABEL=" Reply to Email" COM_COMPONENTBUILDER_CONFIG_ENCRYPTION_DESC="The encryption key for the field encryption is set here." COM_COMPONENTBUILDER_CONFIG_ENCRYPTION_LABEL="Encryption Settings" -COM_COMPONENTBUILDER_CONFIG_EVENT_LABEL="Trigger Event" COM_COMPONENTBUILDER_CONFIG_EVERY_DAY="Every Day" COM_COMPONENTBUILDER_CONFIG_EVERY_FIFTEEN_MINUTES="Every 15 Minutes" COM_COMPONENTBUILDER_CONFIG_EVERY_FIVE_HOURS="Every 5 Hours" @@ -2370,6 +2369,35 @@ COM_COMPONENTBUILDER_CONFIG_EVERY_THIRTY_MINUTES="Every 30 Minutes" COM_COMPONENTBUILDER_CONFIG_EVERY_THIRTY_SECONDS="Every 30 Seconds" COM_COMPONENTBUILDER_CONFIG_EVERY_WEEK="Every Week" COM_COMPONENTBUILDER_CONFIG_EXPANSION="Expansion" +COM_COMPONENTBUILDER_CONFIG_EXPANSIONCRONJOB_NOTE_DESCRIPTION="You must run a cronjob that will trigger the expansion events for JCB.

USE THE FOLLOWING: loading...

Please note that if your Joomla website has a Firewall installed, it will not allow cronjob via direct URL (most of the time), you will then need to adapt the cornjob request to look like a browser. For more info please read https://stackoverflow.com/a/31597823/1429677 +" +COM_COMPONENTBUILDER_CONFIG_EXPANSIONCRONJOB_NOTE_LABEL="Expansion Cronjob" COM_COMPONENTBUILDER_CONFIG_EXPANSION_DESCRIPTION="Properties for this field" COM_COMPONENTBUILDER_CONFIG_EXPANSION_LABEL="Expansion" COM_COMPONENTBUILDER_CONFIG_EXPORT_BUY_LINK_DESCRIPTION="Enter link where your JCB package key can be bought." @@ -2433,7 +2461,7 @@ COM_COMPONENTBUILDER_CONFIG_NOTE_CUSTOM_FOLDER_PATH_DESCRIPTION="The custom fold COM_COMPONENTBUILDER_CONFIG_NOTE_CUSTOM_FOLDER_PATH_LABEL="Moving The Custom Folder" COM_COMPONENTBUILDER_CONFIG_NOTE_DEVELOPMENT_METHOD_DEFAULT_DESCRIPTION="

This method is basically the way JCB has always worked by default.

You have a compiler area, once you have made changes you go to the compiler view and compile your component. Then you have the option to install and/or distribute the Joomla install package.

This can also be called the manual development method.

" COM_COMPONENTBUILDER_CONFIG_NOTE_DEVELOPMENT_METHOD_DEFAULT_LABEL="Default Development Method" -COM_COMPONENTBUILDER_CONFIG_NOTE_DEVELOPMENT_METHOD_EXPANSION_DESCRIPTION="

This method adds auto expansion to the current Joomla automatically.

Below you setup events that trigger auto build and install of a selected set of components. So you do not need to manually compile and install those components any more, the system does all that automatically for you.

So your experience is that you change the field, view or something else in JCB and then the component in Joomla moments later, based on your events and the size of your component, reflect those changed automatically.

This can also be called the automatic development method.

" +COM_COMPONENTBUILDER_CONFIG_NOTE_DEVELOPMENT_METHOD_EXPANSION_DESCRIPTION="

This method adds auto expansion to the current Joomla automatically.

Below you setup the behaviour of a selected set of components that will be auto build and installed. So you do not need to manually compile and install those components any more, the system does all that automatically for you.

So your experience is that you change the field, view or something else in JCB and then the component in Joomla moments later reflect those changed automatically. The latency of the workflow is based on your cronjob frequency and the size of your component. You can pause the build in a few ways, one by actually checking out/opening the Joomla Component view of the component in JCB, or changing the state to unpublish, archive or trashed, or simply remove if from the list below.

This can also be called the automatic development method.

" COM_COMPONENTBUILDER_CONFIG_NOTE_DEVELOPMENT_METHOD_EXPANSION_LABEL="Expansion Development Method" COM_COMPONENTBUILDER_CONFIG_NOTE_DKIM_USE_DESCRIPTION="

Using the below details, you need to configure your DNS by adding a TXT record on your domain: