diff --git a/fields/vmordernumbercounters.php b/fields/vmordernumbercounters.php index b96e01f17230e0ce3b97ae1bacd3862004df25e2..91da6154f9652d25557bc9d33061895fd116f994 100644 --- a/fields/vmordernumbercounters.php +++ b/fields/vmordernumbercounters.php @@ -18,31 +18,29 @@ defined('DS') or define('DS', DIRECTORY_SEPARATOR); if (!class_exists( 'VmConfig' )) require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); VmConfig::loadConfig(); +if (!class_exists('OrdernumberHelperJoomla')) + require_once (dirname(dirname(__FILE__)) . DS . 'ordernumber_helper_joomla.php'); class JFormFieldVmOrdernumberCounters extends JFormField { var $_name = 'vmOrdernumberCounters'; - + protected $countertype; public function __get($name) { - switch ($name) - { + switch ($name) { case 'countertype': return $this->$name; } - return parent::__get($name); } public function __set($name, $value) { - switch ($name) - { + switch ($name) { case 'countertype': $this->$name = (string) $value; break; - default: parent::__set($name, $value); } @@ -59,86 +57,32 @@ class JFormFieldVmOrdernumberCounters extends JFormField { return $return; } - - // VM2 on J2 works, VM3 on J3 works out of the box, but - // VM3 on J2 does NOT work by simply calling vmJsApi::jQuery, because - // the JS is never added to the page header, so we have to add this manually - protected function loadjQuery() { - vmJsApi::jQuery(); - // If we are on Joomla 2.5 and VM 3, manually add the script declarations - // cached in vmJsApi to the document header: - if (version_compare(JVERSION, '3.0', 'lt') && defined('VM_VERSION') && VM_VERSION>=3) { - $document = JFactory::getDocument(); - $scripts = vmJsApi::getJScripts(); - foreach ($scripts as $name => $jsToAdd) { - if($jsToAdd['written']) continue; - $file = $jsToAdd['script'] ? $jsToAdd['script'] : $name; - if(strpos($file,'/')!==0){ - $file = vmJsApi::setPath($file,false,''); - } else if(strpos($file,'//')!==0){ - $file = JURI::root(true).$file; - } + protected function makeJSTranslationsAvailable() { + JText::script('PLG_ORDERNUMBER_JS_NOT_AUTHORIZED'); + JText::script('PLG_ORDERNUMBER_JS_NEWCOUNTER'); + JText::script('PLG_ORDERNUMBER_JS_EDITCOUNTER'); + JText::script('PLG_ORDERNUMBER_JS_INVALID_COUNTERVALUE'); + JText::script('PLG_ORDERNUMBER_JS_MODIFY_FAILED'); + JText::script('PLG_ORDERNUMBER_JS_DELETECOUNTER'); + JText::script('PLG_ORDERNUMBER_JS_DELETE_FAILED'); + JText::script('PLG_ORDERNUMBER_JS_ADD_FAILED'); + JText::script('PLG_ORDERNUMBER_JS_JSONERROR'); + } + + protected function getInput() { + $helper = OrdernumberHelperJoomla::getHelper(); - $ver = ''; - if(!empty($jsToAdd['ver'])) $ver = '?vmver='.$jsToAdd['ver']; - $document->addScript( $file .$ver,"text/javascript",$jsToAdd['defer'],$jsToAdd['async'] ); - vmJsApi::removeJScript($name); - } - } - } - - protected function makeJSTranslationsAvailable() { - JText::script('PLG_ORDERNUMBER_JS_NOT_AUTHORIZED'); - JText::script('PLG_ORDERNUMBER_JS_NEWCOUNTER'); - JText::script('PLG_ORDERNUMBER_JS_EDITCOUNTER'); - JText::script('PLG_ORDERNUMBER_JS_INVALID_COUNTERVALUE'); - JText::script('PLG_ORDERNUMBER_JS_MODIFY_FAILED'); - JText::script('PLG_ORDERNUMBER_JS_DELETECOUNTER'); - JText::script('PLG_ORDERNUMBER_JS_DELETE_FAILED'); - JText::script('PLG_ORDERNUMBER_JS_ADD_FAILED'); - JText::script('PLG_ORDERNUMBER_JS_JSONERROR'); - } - protected function getInput() { - $pluginpath = '/plugins/vmshopper/ordernumber/ordernumber/'; - $doc = JFactory::getDocument()->addStyleSheet(JURI::root(true) . $pluginpath . 'assets/css/ordernumber.css'); - $this->makeJSTranslationsAvailable(); - $this->loadjQuery(); - $doc->addScript(JURI::root(true).$pluginpath . 'assets/js/ordernumber.js'); - - // Look up the current counters - $db = JFactory::getDBO(); - $db->setQuery('SELECT `number_format`, `count` FROM `#__virtuemart_shopper_plg_ordernumber` WHERE `number_type`='.$db->quote($this->countertype) . ' ORDER BY `number_format`;' ); - $counters = $db->loadObjectList(); - // Joomla 2.x uses <li> for the params and float:left on the controls, so we need to add that too - $float = ""; - if (version_compare(JVERSION, '3.0', 'lt')) { - $float = "float: left; "; - } + $doc = JFactory::getDocument()->addStyleSheet($helper->urlPath('css', 'ordernumber.css')); +// $this->makeJSTranslationsAvailable(); + $helper->loadjQuery(); + $doc->addScript($helper->urlPath('js', 'ordernumber.js')); - $html=array(); - $html[] = "<img src='".JURI::root(true).$pluginpath . "assets/images/loading.gif' class='vm-ordernumber-loading' style=\"display: none; position: absolute; top: 2px; left: 0px; z-index: 9999;\"/><table class=\"vmordernumber-countertable table-striped \" style=\"display: inline-table; $float\">"; - $html[] = " <tr>"; - $html[] = " <th class='counter_format'>".JText::_('PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER')."</th>"; - $html[] = " <th class='counter_value'>".JText::_('PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE'). "</th>"; - $html[] = " <th class='counter_buttons'></th>"; - $html[] = " </tr>"; - $html[] = " <colgroup><col class='counter_type'><col style=\"text-align: center\" ><col ></colgroup>"; - foreach ($counters as $c) { - $displayfmt = $c->number_format; - if ($displayfmt=="") { - $displayfmt = JText::_ ('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL'); - } - $html[] = " <tr class='counter_row counter_type_$this->countertype'>"; - $html[] = " <td class='counter_format'>" . (string)$displayfmt . "</td>"; - $html[] = " <td class='counter_value'>" . (string)$c->count . "</td>"; - $html[] = " <td class='counter_buttons'><div class='ordernumber-ajax-loading'><img src='" .JURI::root(true).$pluginpath . "assets/images/icon-16-edit.png' class='vmordernumber-counter-editbtn vmordernumber-btn' onClick='ajaxEditCounter(this, " . json_encode($this->countertype) . ", ".json_encode($c->number_format).", $c->count)' /></div><div class='ordernumber-ajax-loading'><img src='" . JURI::root(true).$pluginpath . "assets/images/icon-16-delete.png' class='vmordernumber-counter-deletebtn vmordernumber-btn' onClick='ajaxDeleteCounter(this, ".json_encode($this->countertype).", ".json_encode($c->number_format).", $c->count)' /></div></td>"; - $html[] = " </tr>"; - } - $html[] = " <tr class='addcounter_row'>"; - $html[] = " <td colspan=3 class='counter_add'><div class='vmordernumber-counter-addbtn vmordernumber-btn' onClick='ajaxAddCounter(this, " . json_encode($this->countertype).")'><div class='ordernumber-ajax-loading'><img src='" . JURI::root(true).$pluginpath . "assets/images/icon-16-new.png' class='vmordernumber-counter-addbtn' /></div>" . JText::_('PLG_ORDERNUMBER_COUNTERLIST_ADD') . "</div></td>"; - $html[] = " </tr>"; - $html[] = "</table>"; - return implode("\n", $html); - } -} \ No newline at end of file + // Look up the current counters + $db = JFactory::getDBO(); + $db->setQuery('SELECT `number_format`, `count` FROM `#__virtuemart_shopper_plg_ordernumber` WHERE `number_type`='.$db->quote($this->countertype) . ' ORDER BY `number_format`;' ); + $counters = $db->loadObjectList(); + + return $helper->counter_modification_create_table ($this->countertype, $counters); + } +} diff --git a/fields/vmordernumberreplacements.php b/fields/vmordernumberreplacements.php index 315f2d56ddc725669d881c2386252f9b6baf6c28..b88dcc949aa8cd09e5dcda0b8ee94c37deb1d38e 100644 --- a/fields/vmordernumberreplacements.php +++ b/fields/vmordernumberreplacements.php @@ -15,180 +15,24 @@ defined('_JEXEC') or die(); */ defined('DS') or define('DS', DIRECTORY_SEPARATOR); -if (!class_exists( 'VmConfig' )) - require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); -VmConfig::loadConfig(); +// if (!class_exists( 'VmConfig' )) +// require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); +// VmConfig::loadConfig(); +if (!class_exists('OrdernumberHelperJoomla')) + require_once (dirname(dirname(__FILE__)) . DS . 'ordernumber_helper_joomla.php'); class JFormFieldVmOrdernumberReplacements extends JFormField { var $_name = 'vmOrdernumberReplacements'; - static $pluginpath = '/plugins/vmshopper/ordernumber/ordernumber/'; - - protected $countertype; - - // VM2 on J2 works, VM3 on J3 works out of the box, but - // VM3 on J2 does NOT work by simply calling vmJsApi::jQuery, because - // the JS is never added to the page header, so we have to add this manually - protected function loadjQuery() { - vmJsApi::jQuery(); - // TODO: jquery::ui available only in J3: - if (version_compare(JVERSION, '3.0', 'lt')) { - } else { - JHtml::_('jquery.ui', array('core', 'sortable')); - } - // If we are on Joomla 2.5 and VM 3, manually add the script declarations - // cached in vmJsApi to the document header: - if (version_compare(JVERSION, '3.0', 'lt') && defined('VM_VERSION') && VM_VERSION>=3) { - $document = JFactory::getDocument(); - $scripts = vmJsApi::getJScripts(); - foreach ($scripts as $name => $jsToAdd) { - if($jsToAdd['written']) continue; - $file = $jsToAdd['script'] ? $jsToAdd['script'] : $name; - - if(strpos($file,'/')!==0){ - $file = vmJsApi::setPath($file,false,''); - } else if(strpos($file,'//')!==0){ - $file = JURI::root(true).$file; - } - - $ver = ''; - if(!empty($jsToAdd['ver'])) $ver = '?vmver='.$jsToAdd['ver']; - $document->addScript( $file .$ver,"text/javascript",$jsToAdd['defer'],$jsToAdd['async'] ); - vmJsApi::removeJScript($name); - } - } - } - - static function img_url($file) { - return JURI::root(true) . self::$pluginpath . 'assets/images/' . $file; - } - static function css_url($file) { - return JURI::root(true) . self::$pluginpath . 'assets/css/' . $file; - } - static function js_url($file) { - return JURI::root(true) . self::$pluginpath . 'assets/js/' . $file; - } - static function __($string) { - return JText::_($string); - } - - protected function makeJSTranslationsAvailable() { -// JText::script('PLG_ORDERNUMBER_JS_JSONERROR'); - } - protected function getInput() { - - $html=array(); - $doc = JFactory::getDocument()->addStyleSheet(self::css_url('ordernumber.css')); - $this->loadjQuery(); - $doc->addScript( self::js_url('ordernumber.js')); - $this->makeJSTranslationsAvailable(); - - - $value = $this->value; -// $html[] = "<pre> value: ".print_r($value,1)."</pre>"; -// $html[] = "<pre>Form Field: ".print_r($this,1)."</pre>"; - $variables = array(); - if (!is_array($value)) - $value = array(); - - if (!empty($value)) { - $keys = array_keys($value); - foreach (array_keys($value[$keys[0]]) as $i) { - $entry = array(); - foreach ($keys as $k) { - $entry[$k] = $value[$k][$i]; - } - $variables[] = $entry; - } - } - - $id = $this->id; - $name = $this->name; + protected function getInput() { + $helper = OrdernumberHelperJoomla::getHelper(); + $doc = JFactory::getDocument()->addStyleSheet($helper->urlPath('css', 'ordernumber.css')); + $helper->loadjQuery(); + $doc->addScriptDeclaration($helper->createJSSetup()); + $doc->addScript( $helper->urlPath('js', 'ordernumber.js')); - -// $html[] = "<pre>Variables: ".print_r($variables,1)."</pre>"; - $html[] = '<table id="ordernumber_variables_template" style="display:none">'; - $html[] = $this->create_replacements_row_html($name, array(), 'disabled'); - $html[] = '</table>'; - - $html[] = '<table id="ordernumber_variables" class="ordernumber_variables widefat wc_input_table sortable" cellspacing="0">'; - $columns = array( - 'variables_ifvar' => self::__('PLG_ORDERNUMBER_REPL_IFVAR'), - 'variables_ifop' => '', - 'variables_ifval' => self::__('PLG_ORDERNUMBER_REPL_IFVAL'), - 'variables_then' => self::__(''), - 'variables_thenvar' => self::__('PLG_ORDERNUMBER_REPL_SETVAR'), - 'variables_thenval' => self::__('PLG_ORDERNUMBER_REPL_TOVAL'), - 'sort' => '', - 'variables_settings' => '', - ); - $html[] = ' <thead>'; - $html[] = ' <tr class="ordernumber_variables_header">'; - foreach ( $columns as $key => $column ) { - $html[] = '<th class="' . $key . '">' . htmlspecialchars( $column ) . '</th>'; - } - $html[] = ' </tr>'; - $html[] = ' <tr id="ordernumber-replacements-empty-row" class="oton-empty-row-notice ' . (empty($variables)?"":"rowhidden") . '">'; - $html[] = ' <td class="oton-empty-row-notice" colspan="8">'; - $html[] = ' <em>' . self::__('PLG_ORDERNUMBER_REPL_NOCUSTOMVARS') . '</em>'; - $html[] = ' <input type="hidden" name="' . $name . '" value="" ' . (empty($variables))?'':'disabled' . '>'; - $html[] = ' </td>'; - $html[] = ' </tr>'; - $html[] = ' </thead>'; - $html[] = ' <colgroup>'; - foreach ($columns as $key => $column) { - $html[] = '<col class="' . $key . '" />'; - } - $html[] = ' </colgroup>'; - $html[] = ''; - $html[] = ' <tbody>'; - foreach ($variables as $var) { - $html[] = $this->create_replacements_row_html($name, $var); - } - $html[] = ' </tbody>'; - $html[] = ' <tfoot>'; - $html[] = ' <tr class="addreplacement_row">'; - $html[] = ' <td colspan=8 class="variable_add">'; - $html[] = ' <div class="ordernumber-variables-addbtn ordernumber-btn" onClick="ordernumberVariablesAddRow(\'ordernumber_variables_template\', \'ordernumber_variables\')">'; - $html[] = ' <div class="ordernumber-ajax-loading"><img src="' . self::img_url( 'icon-16-new.png' ) . '" class="ordernumber-counter-addbtn" /></div>'; - $html[] = self::__('PLG_ORDERNUMBER_REPL_ADDVAR'); - $html[] = ' </div>'; - $html[] = ' </td>'; - $html[] = ' </tr>'; - $html[] = ' </tfoot>'; - $html[] = '</table>'; - return implode("\n", $html); + $variables = $helper->transposeCustomVariables($this->value); + return $helper->custom_variables_create_table($this->name, $variables); } - protected function create_replacements_row_html($name, $values = array(), $disabled = '') { - $operator = (isset($values['conditionop'])?$values['conditionop']:''); - $operators = array( - 'equals' => '=', - 'contains' => self::__('PLG_ORDERNUMBER_REPL_OP_CONTAINS'), - 'smaller' => '<', - 'smallerequal' => '<=', - 'larger' => '>', - 'largerequal' => '>=', - 'startswith' => self::__('PLG_ORDERNUMBER_REPL_OP_STARTS'), - 'endswith' => self::__('PLG_ORDERNUMBER_REPL_OP_ENDS'), - ); - $html = ' - <tr> - <td class="variables_ifvar"><input name="' . $name . '[conditionvar][]" value="' . (isset($values['conditionvar'])?$values['conditionvar']:'') . '" ' . $disabled . '/></td> - <td class="variables_ifop" ><select name="' . $name . '[conditionop][]" ' . $disabled . ' style="width: 100px">'; - foreach ($operators as $op => $opname) { - $html .= ' <option value="' . $op . '" ' . (($op === $operator)?'selected':'') . '>' . htmlspecialchars($opname) . '</option>'; - } - $html .= '</select></td> - <td class="variables_ifval" ><input name="' . $name . '[conditionval][]" value="' . (isset($values['conditionval'])?$values['conditionval']:'') . '" ' . $disabled . '/></td> - <td class="variables_then">=></td> - <td class="variables_thenvar"><input name="' . $name . '[newvar][]" value="' . (isset($values['newvar'])?$values['newvar']:'') . '" ' . $disabled . '/></td> - <td class="variables_thenval"><input name="' . $name . '[newval][]" value="' . (isset($values['newval'])?$values['newval']:'') . '" ' . $disabled . '/></td> - <td class="sort"></td> - <td class="variables_settings"><img src="' . self::img_url( 'icon-16-delete.png' ) . '" class="ordernumber-replacement-deletebtn ordernumber-btn"></td> - </tr>'; - return $html; - } - - } \ No newline at end of file diff --git a/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini b/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini index fc29d641038f58c2dfcc29e21c813cb4fc71badf..d70ac7a74e6ded896cfb1b60d77bd7ae4487ad55 100644 --- a/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini +++ b/language/en-GB/en-GB.plg_vmshopper_ordernumber.ini @@ -59,15 +59,15 @@ PLG_ORDERNUMBER_FIELDSET_INVOICENUMBER="Invoice Numbers" PLG_ORDERNUMBER_FIELDSET_CUSTOMERNUMBER="Customer Numbers" PLG_ORDERNUMBER_FIELDSET_REPLACEMENTS="Custom Variables" -PLG_ORDERNUMBER_JS_NOT_AUTHORIZED="You are not authorized to modify order number counters." -PLG_ORDERNUMBER_JS_NEWCOUNTER="Please enter the format/name of the new counter:" -PLG_ORDERNUMBER_JS_DELETECOUNTER="Really delete counter '{0}' with value '{1}'?" -PLG_ORDERNUMBER_JS_EDITCOUNTER="{0}Please enter the new value for the counter '{1}' (current value: {2}):" -PLG_ORDERNUMBER_JS_INVALID_COUNTERVALUE="You entered an invalid value for the counter.\n\n" -PLG_ORDERNUMBER_JS_MODIFY_FAILED="Failed modifying counter {0}" -PLG_ORDERNUMBER_JS_DELETE_FAILED="Failed deleting counter {0}" -PLG_ORDERNUMBER_JS_ADD_FAILED="Failed adding counter {0}" -PLG_ORDERNUMBER_JS_JSONERROR="Error reading response from server:" +ORDERNUMBER_JS_NOT_AUTHORIZED="You are not authorized to modify order number counters." +ORDERNUMBER_JS_NEWCOUNTER="Please enter the format/name of the new counter:" +ORDERNUMBER_JS_DELETECOUNTER="Really delete counter '{0}' with value '{1}'?" +ORDERNUMBER_JS_EDITCOUNTER="{0}Please enter the new value for the counter '{1}' (current value: {2}):" +ORDERNUMBER_JS_INVALID_COUNTERVALUE="You entered an invalid value for the counter.\n\n" +ORDERNUMBER_JS_MODIFY_FAILED="Failed modifying counter {0}" +ORDERNUMBER_JS_DELETE_FAILED="Failed deleting counter {0}" +ORDERNUMBER_JS_ADD_FAILED="Failed adding counter {0}" +ORDERNUMBER_JS_JSONERROR="Error reading response from server:" PLG_ORDERNUMBER_REPL_IFVAR="If variable ..." PLG_ORDERNUMBER_REPL_IFVAL="Value" diff --git a/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini b/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini index fc29d641038f58c2dfcc29e21c813cb4fc71badf..d70ac7a74e6ded896cfb1b60d77bd7ae4487ad55 100644 --- a/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini +++ b/language/en-GB/en-GB.plg_vmshopper_ordernumber.sys.ini @@ -59,15 +59,15 @@ PLG_ORDERNUMBER_FIELDSET_INVOICENUMBER="Invoice Numbers" PLG_ORDERNUMBER_FIELDSET_CUSTOMERNUMBER="Customer Numbers" PLG_ORDERNUMBER_FIELDSET_REPLACEMENTS="Custom Variables" -PLG_ORDERNUMBER_JS_NOT_AUTHORIZED="You are not authorized to modify order number counters." -PLG_ORDERNUMBER_JS_NEWCOUNTER="Please enter the format/name of the new counter:" -PLG_ORDERNUMBER_JS_DELETECOUNTER="Really delete counter '{0}' with value '{1}'?" -PLG_ORDERNUMBER_JS_EDITCOUNTER="{0}Please enter the new value for the counter '{1}' (current value: {2}):" -PLG_ORDERNUMBER_JS_INVALID_COUNTERVALUE="You entered an invalid value for the counter.\n\n" -PLG_ORDERNUMBER_JS_MODIFY_FAILED="Failed modifying counter {0}" -PLG_ORDERNUMBER_JS_DELETE_FAILED="Failed deleting counter {0}" -PLG_ORDERNUMBER_JS_ADD_FAILED="Failed adding counter {0}" -PLG_ORDERNUMBER_JS_JSONERROR="Error reading response from server:" +ORDERNUMBER_JS_NOT_AUTHORIZED="You are not authorized to modify order number counters." +ORDERNUMBER_JS_NEWCOUNTER="Please enter the format/name of the new counter:" +ORDERNUMBER_JS_DELETECOUNTER="Really delete counter '{0}' with value '{1}'?" +ORDERNUMBER_JS_EDITCOUNTER="{0}Please enter the new value for the counter '{1}' (current value: {2}):" +ORDERNUMBER_JS_INVALID_COUNTERVALUE="You entered an invalid value for the counter.\n\n" +ORDERNUMBER_JS_MODIFY_FAILED="Failed modifying counter {0}" +ORDERNUMBER_JS_DELETE_FAILED="Failed deleting counter {0}" +ORDERNUMBER_JS_ADD_FAILED="Failed adding counter {0}" +ORDERNUMBER_JS_JSONERROR="Error reading response from server:" PLG_ORDERNUMBER_REPL_IFVAR="If variable ..." PLG_ORDERNUMBER_REPL_IFVAL="Value" diff --git a/ordernumber.php b/ordernumber.php index 5d328f3d8d7b4b49a5a12cd051f12235625bdcbb..40abd09ee24c9997144bd130c92ed27248976753 100644 --- a/ordernumber.php +++ b/ordernumber.php @@ -6,21 +6,39 @@ * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html **/ -defined('_JEXEC') or die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' ) ; +if ( !defined( 'ABSPATH' ) and !defined('_JEXEC') ) { + die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' ) ; +} if (!class_exists('vmShopperPlugin')) require(JPATH_VM_PLUGINS . DS . 'vmshopperplugin.php'); -if (!class_exists( 'VmConfig' )) - require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); -VmConfig::loadConfig(); +// if (!class_exists( 'VmConfig' )) +// require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); +// VmConfig::loadConfig(); +if (!class_exists('OrdernumberHelperJoomla')) + require_once (dirname(__FILE__) . DS . 'ordernumber_helper_joomla.php'); class plgVmShopperOrdernumber extends vmShopperPlugin { + protected $helper = null; - function __construct(& $subject, $config) { - parent::__construct($subject, $config); - /* Create the database table */ - $this->tableFields = array_keys ($this->getTableSQLFields ()); - } + function __construct(& $subject, $config) { + parent::__construct($subject, $config); + /* Create the database table */ + $this->tableFields = array_keys ($this->getTableSQLFields ()); + $this->helper = new OrdernumberHelperJoomla(); + $this->helper->tableName = $this->_tablename; + + $this->helper->registerCallback('setupStoreReplacements', array($this, 'setupStoreReplacements')); + $this->helper->registerCallback('setupOrderReplacements', array($this, 'setupOrderReplacements')); + $this->helper->registerCallback('setupUserReplacements', array($this, 'setupUserReplacements')); + $this->helper->registerCallback('setupShippingReplacements', array($this, 'setupShippingReplacements')); + $this->helper->registerCallback('setupThirdPartyReplacements', array($this, 'setupThirdPartyReplacements')); + + } + /** + * Glue functions for the OrdernumberHelper + */ + public function getVmPluginCreateTableSQL () { return $this->createTableSQL ('VM Shopper plugin: custom order and invoice numbers'); } @@ -38,86 +56,8 @@ class plgVmShopperOrdernumber extends vmShopperPlugin { // We don't need this function, but the parent class declares it abstract, so we need to overload function plgVmOnUpdateOrderBEShopper($_orderID) {} - function _getCounter($nrtype, $format, $default=0) { - $db = JFactory::getDBO(); - - /* prevent sql injection attacks by escaping the user-entered format! Empty for global counter... */ - /* For global counting, simply read the empty number_format entries! */ - $q = 'SELECT `count` FROM `'.$this->_tablename.'` WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); - $db->setQuery($q); - $existing = $db->loadResult(); - $count = $existing?$existing:$default; - return $count; - } - - function _counterExists($nrtype, $format) { - $db = JFactory::getDBO(); - $q = 'SELECT `count` FROM `'.$this->_tablename.'` WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); - $db->setQuery($q); - return ($db->loadResult() != null); - } - - // Insert new counter value into the db - function _addCounter($nrtype, $format, $value) { - $db = JFactory::getDBO(); - $q = 'INSERT INTO `'.$this->_tablename.'` (`count`, `number_type`, `number_format`) VALUES ('.(int)$value.','.$db->quote($nrtype).', '.$db->quote($format).')'; - $db->setQuery( $q ); - $db->query(); - return $db->getAffectedRows(); - } - - // Insert new counter value into the db or update existing one - function _setCounter($nrtype, $format, $value) { - $db = JFactory::getDBO(); - $q = 'UPDATE `'.$this->_tablename.'` SET `count`= "'.(int)$value.'" WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); - $db->setQuery( $q ); - $db->query(); - if ($db->getAffectedRows()<1) { - return $this->_addCounter($nrtype, $format, $value); - } else { - return $db->getAffectedRows(); - } - } - - // Insert new counter value into the db or update existing one - function _deleteCounter($nrtype, $format) { - $db = JFactory::getDBO(); - $format = $db->escape ($format); - $q = 'DELETE FROM `'.$this->_tablename.'` WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); - $db->setQuery( $q ); - $db->query(); - return $db->getAffectedRows(); - } - - /* Return a random "string" of the given length taken from the given alphabet */ - static function randomString($alphabet, $len) { - $alen = strlen($alphabet); - $r = ""; - for ($n=0; $n<$len; $n++) { - $r .= $alphabet[mt_rand(0, $alen-1)]; - } - return $r; - } - - function replaceRandom ($match) { - /* the regexp matches (random)(Type)(Len) as match, Type and Len is optional */ - $len = ($match[3]?$match[3]:1); - // Fallback: If no Type is given, use Digit - $alphabet = "0123456789"; - // Select the correct alphabet depending on Type - switch (strtolower($match[2])) { - case "digit": $alphabet = "0123456789"; break; - case "hex": $alphabet = "0123456789abcdef"; break; - case "letter": $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; break; - case "uletter": $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; break; - case "lletter": $alphabet = "abcdefghijklmnopqrstuvwxyz"; break; - case "alphanum": $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; break; - } - return self::randomString ($alphabet, $len); - } - /* Extract the country information from the given ID */ - static function getCountryFromID ($country_id) { + protected static function getCountryFromID ($country_id) { $db = JFactory::getDBO(); $query = 'SELECT * FROM `#__virtuemart_countries` WHERE `virtuemart_country_id` = ' . (int)$country_id; $db->setQuery($query); @@ -126,24 +66,6 @@ class plgVmShopperOrdernumber extends vmShopperPlugin { - protected function setupDateTimeReplacements (&$reps, $details, $nrtype) { - $utime = microtime(true); - $reps["[year]"] = date ("Y", $utime); - $reps["[year2]"] = date ("y", $utime); - $reps["[month]"] = date("m", $utime); - $reps["[day]"] = date("d", $utime); - $reps["[hour]"] = date("H", $utime); - $reps["[hour12]"] = date("h", $utime); - $reps["[ampm]"] = date("a", $utime); - $reps["[minute]"] = date("i", $utime); - $reps["[second]"] = date("s", $utime); - $milliseconds = (int)(1000*($utime - (int)$utime)); - $millisecondsstring = sprintf('%03d', $milliseconds); - $reps["[decisecond]"] = $millisecondsstring[0]; - $reps["[centisecond]"] = substr($millisecondsstring, 0, 2); - $reps["[millisecond]"] = $millisecondsstring; - } - protected function setupStoreReplacements (&$reps, $details, $nrtype) { if (isset($details->virtuemart_vendor_id)) $reps["[vendorid]"] = $details->virtuemart_vendor_id; @@ -255,7 +177,6 @@ class plgVmShopperOrdernumber extends vmShopperPlugin { } - protected function setupUserReplacements (&$reps, $details, $nrtype) { // TODO: Implement shopper group! $reps["[userid]"] = $details->virtuemart_user_id; @@ -275,160 +196,7 @@ class plgVmShopperOrdernumber extends vmShopperPlugin { JPluginHelper::importPlugin('vmshopper'); JDispatcher::getInstance()->trigger('onVmOrdernumberGetVariables',array(&$reps, $nrtype, $details)); } - - protected function setupReplacements($nrtype, $details) { - $reps = array(); - $this->setupDateTimeReplacements($reps, $details, $nrtype); - $this->setupStoreReplacements($reps, $details, $nrtype); - $this->setupOrderReplacements($reps, $details, $nrtype); - $this->setupUserReplacements($reps, $details, $nrtype); - $this->setupShippingReplacements($reps, $details, $nrtype); - $this->setupThirdPartyReplacements($reps, $details, $nrtype); - return $reps; - } - - protected function setupCustomVariables ($nrtype, $order, $reps, $customvars) { - foreach ($customvars as $c) { - $conditionvar = strtolower($c['conditionvar']); - $op = $c['conditionop']; - - $found = false; - $match = false; - $compareval = null; - - if (isset($reps[$conditionvar])) { - $found = true; - $compareval = $reps[$conditionvar]; - } elseif (isset($reps['['.$conditionvar.']'])) { - $found = true; - $compareval = $reps['['.$conditionvar.']']; - }/* elseif ($order && $compareval = $order->getData($conditionvar)) { - // TODO: Handle order property - $found = true; - }*/ else { - // TODO: Handly other possible properties! - // TODO: Print out warning that variable could not be found. - } - if ($found) { - $condval = $c['conditionval']; - switch ($op) { - case 'nocondition': - $match = true; break; - case 'equals': - $match = ($compareval == $condval); break; - case 'contains': - if (is_array($compareval)) { - $match = in_array($condval, $compareval); - } else { - $match = strpos ($compareval, $condval); - } - break; - case 'smaller': - $match = ($compareval<$condval); break; - case 'smallerequal': - $match = ($compareval<=$condval); break; - case 'larger': - $match = ($compareval>$condval); break; - case 'largerequal': - $match = ($compareval>=$condval); break; - case 'startswith': - $match = (substr("$compareval", 0, strlen("$condval")) === "$condval"); break; - case 'endswith': - $match = (substr("$compareval", -strlen("$condval")) === "$condval"); break; - } - } elseif (empty($conditionvar)) { - $match = true; - } - if ($match) { - $varname = '['.strtolower($c['newvar']).']'; - $reps[$varname] = $c['newval']; - } - } - return $reps; - } - - // Allow the user to override the format like any other custom variable: - protected function setupNumberFormatString($fmt, $type, $order, $reps) { - if (isset($reps['['.$type.'_format]'])) { - return $reps['['.$type.'_format]']; - } else { - return $fmt; - } - } - - protected function doReplacements ($fmt, $reps) { - // First, replace all random...[n] fields. This needs to be done with a regexp and a callback: - $fmt = preg_replace_callback ('/\[(random)(.*?)([0-9]*?)\]/', array($this, 'replaceRandom'), $fmt); - // Only use string-valued variables for replacement (array-valued variables can be used in custom variable definitions!) - $reps = array_filter($reps, function($v) { return !is_array($v);} ); - return str_ireplace (array_keys($reps), array_values($reps), $fmt); - } - - protected function extractCounterSettings ($fmt, $type, $ctrsettings) { - // First, extract all counter settings, i.e. all strings of the form [#####:startval/increment] or [####/increment:startval] - $regexp = '%\[(#+)(/([0-9]+))?(:([0-9]+))?(/([0-9]+))?\]%'; - - if (preg_match($regexp, $fmt, $counters)) { - // $counters is an array of the form: - // Array ( - // [0] => [#####:100/3] - // [1] => ##### - // [2] => - // [3] => - // [4] => :100 - // [5] => 100 - // [6] => /3 - // [7] => 3 - // ) - $ctrsettings["${type}_padding"] = strlen($counters[1]); - if (!empty($counters[2])) { - // $counters[2] contains the whole "/n" part, while $counters[3] contains just the step itself - $ctrsettings["${type}_step"] = $counters[3]; - } - if (!empty($counters[4])) { - // $counters[4] contains the whole ":n" part, while $counters[5] contains just the start value itself - $ctrsettings["${type}_start"] = $counters[5]; - } - - if (!empty($counters[6])) { - // $counters[6] contains the whole ":n" part, while $counters[7] contains just the start value itself - $ctrsettings["${type}_step"] = $counters[7]; - } - - $fmt = preg_replace($regexp, "#", $fmt); - } - // Split at a | to get the number format and a possibly different counter increment format - // If a separate counter format is given after the |, use it, otherwise reuse the number format itself as counter format - $parts = explode ("|", $fmt); - $ctrsettings["${type}_format"] = $parts[0]; - $ctrsettings["${type}_counter"] = ($ctrsettings["${type}_global"]==1)?"":$parts[(count($parts)>1)?1:0]; - - return $ctrsettings; - } - /* replace the variables in the given format. $type indicates the type of number. */ - function createNumber ($fmt, $type, $order, $customvars, $ctrsettings) { - $reps = $this->setupReplacements ($type, $order); - $reps = $this->setupCustomVariables ($type, $order, $reps, $customvars); - $format = $this->setupNumberFormatString($fmt, $type, $order, $reps); - $format = $this->doReplacements($format, $reps); - $ctrsettings = $this->extractCounterSettings ($format, $type, $ctrsettings); - -// JFactory::getApplication()->enqueueMessage("<pre>Replacements for $type:".print_r($reps,1)."</pre>", 'error'); - // Increment the counter only if the format contains a placeholder for it! - if (strpos($ctrsettings["${type}_format"], "#") !== false) { - $countername = $ctrsettings["${type}_counter"]; - // Look up the current counter - $count = $this->_getCounter($type, $countername, $ctrsettings["${type}_start"] - $ctrsettings["${type}_step"]) + $ctrsettings["${type}_step"]; - $this->_setCounter($type, $countername, $count); - // return the format with the counter inserted - $number = str_replace ("#", sprintf('%0' . $ctrsettings["${type}_padding"] . 's', $count), $ctrsettings["${type}_format"]); - } else { - $number = $ctrsettings["${type}_format"]; - } - return $number; - } - function assignNumber($order, $type='ordernumber', $default="#") { if ($this->params->get('customize_'.$type, 0)) { $fmt = $this->params->get ($type.'_format', $default); @@ -440,28 +208,8 @@ class plgVmShopperOrdernumber extends vmShopperPlugin { "${type}_step" => 1, "${type}_start" => 1, ); - $cvar = $this->params->get ('replacements', array()); - // Even though the replacements are created and stored as an array, they are retrieved as a stdClass object: - if (is_object($cvar)) $cvar = (array)$cvar; - if (!is_array($cvar)) - $cvar = array(); - // The customvars are stored in transposed form (for technical reasons, since there is no trigger - // called when the corresponding form field from the plugin param is saved) - $customvars = array(); - - if (!empty($cvar)) { - $keys = array_keys($cvar); - foreach (array_keys($cvar[$keys[0]]) as $i) { - $entry = array(); - foreach ($keys as $k) { - $entry[$k] = $cvar[$k][$i]; - } - $customvars[] = $entry; - } - } - - - $number = $this->createNumber ($fmt, $type, $order, $customvars, $ctrsettings); + $customvars = $this->helper->transposeCustomVariables($this->params->get ('replacements', array())); + $number = $this->helper->createNumber ($fmt, $type, $order, $customvars, $ctrsettings); return $number; } else { return false; @@ -542,30 +290,23 @@ class plgVmShopperOrdernumber extends vmShopperPlugin { $json['success'] = 0; // default: unsuccessfull switch ($action) { case "deleteCounter": - $json['success'] = $this->_deleteCounter($nrtype, $counter); + $json['success'] = $this->helper->deleteCounter($nrtype, $counter); break; case "addCounter": $value = vRequest::getInt('value',0); - if ($this->_counterExists($nrtype, $counter)) { + if ($this->helper->counterExists($nrtype, $counter)) { $json['error'] = JText::sprintf('PLG_ORDERNUMBER_COUNTERLIST_EXISTS', $counter); $json['success'] = false; } else { - $json['success'] = $this->_addCounter($nrtype, $counter, $value); + $json['success'] = $this->helper->addCounter($nrtype, $counter, $value); // Return the table row for the new counter in the JSON: - $pluginpath = '/plugins/vmshopper/ordernumber/ordernumber/'; - $displayfmt = ($counter=="") ? JText::_('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL') : $counter; - $html=array(); - $html[] = "<tr class='counter_row counter_type_$nrtype'>"; - $html[] = " <td class='counter_format'>" . (string)$displayfmt . "</td>"; - $html[] = " <td class='counter_value'>" . (string)$value . "</td>"; - $html[] = " <td class='counter_buttons'><img src='" .JURI::root(true).$pluginpath . "assets/images/icon-16-edit.png' class='vmordernumber-counter-editbtn vmordernumber-btn' onClick='ajaxEditCounter(this, ".json_encode($nrtype).", ".json_encode($counter).", $value)' /><img src='" . JURI::root(true).$pluginpath . "assets/images/icon-16-delete.png' class='vmordernumber-counter-deletebtn vmordernumber-btn' onClick='ajaxDeleteCounter(this, ".json_encode($nrtype).", ".json_encode($counter).", $value)' /></td>"; - $html[] = "</tr>"; - $json['newrow'] = implode("\n", $html); + $json['row'] = $this->helper->counter_modification_create_row($nrtype, $counter, $value); } break; case "setCounter": $value = vRequest::getInt('value'); - $json['success'] = $this->_setCounter($nrtype, $counter, $value); + $json['success'] = $this->helper->setCounter($nrtype, $counter, $value); + $json['row'] = $this->helper->counter_modification_create_row($nrtype, $counter, $value); break; } diff --git a/ordernumber/assets/css/ordernumber.css b/ordernumber/assets/css/ordernumber.css index 27ecd74be2df0a382aba16c35906505dfb63214b..953f955b119f348a03a3c4c2895dbbb239cf5cbe 100644 --- a/ordernumber/assets/css/ordernumber.css +++ b/ordernumber/assets/css/ordernumber.css @@ -1,12 +1,10 @@ -td.counter_value { - text-align: center; -} -table.vmordernumber-countertable { +table.ordernumber-countertable { border: 1px solid #888888; + display: inline-table; } -table.vmordernumber-countertable.table-striped tbody > tr:nth-child(odd) > th { +table.ordernumber-countertable.table-striped tbody > tr:nth-child(odd) > th { background: #E0E0E0; } .vmordernumber-btn { @@ -16,15 +14,18 @@ table.vmordernumber-countertable.table-striped tbody > tr:nth-child(odd) > th { col.counter_type, th.counter_type, td.counter_type { display:none; } +td.counter_value { + text-align: center; +} -fieldset table.vmordernumber-countertable img { +fieldset table.ordernumber-countertable img { padding: 0; margin: 0; } -div.ordernumber-ajax-loading, div.vmordernumber-counter-addbtn { +div.ordernumber-ajax-loading, div.ordernumber-counter-addbtn { display: inline; } -div.ordernumber-ajax-loading, div.ordernumber-ajax-loading img.vmordernumber-btn { +div.ordernumber-ajax-loading, div.ordernumber-ajax-loading img.ordernumber-btn { position: relative; top: 0; left: 0; } @@ -32,6 +33,14 @@ div.ordernumber-ajax-loading img { z-index:0; } +img.ordernumber-loading { + display: none; + position: absolute; + top: 2px; + left: 0px; + z-index: 9999; +} + /* Counter custom variable replacements */ @@ -96,3 +105,6 @@ col.variables_thenvar, col.variables_thenval { text-align: center; width: 20px; } + + + diff --git a/ordernumber/assets/js/ordernumber.js b/ordernumber/assets/js/ordernumber.js index c83dfb22cc9744d3b5c25c4e31e749ff3048226e..ea9e7fb5943ad63a21507fbf4b075da26fc5c74d 100644 --- a/ordernumber/assets/js/ordernumber.js +++ b/ordernumber/assets/js/ordernumber.js @@ -3,21 +3,6 @@ * Javascript for the counter modification table * **********************************************************************************/ -var updateMessages = function(messages, area) { - jQuery( "#system-message-container #system-message ."+area+"-message").remove(); - // Extract the messages from the returned string, add the ordernumber-message class (so the next ajax call - // can remove them again) and then move the messages to the original message container. - // Things are complicated by the fact that no #system-message element exists if no messages were printed so far - var newmessages = jQuery( messages ).find("div.alert, .message").addClass(area+"-message"); - if (!jQuery( "#system-message-container #system-message").length && newmessages.length) { - if (jQuery(newmessages).first().prop("tagName")=="dt") { // Joomla 2.x: - jQuery( "#system-message-container" ).append( "<dl id='system-message'></div>" ); - } else { - jQuery( "#system-message-container" ).append( "<div id='system-message'></div>" ); - } - } - newmessages.appendTo( "#system-message-container #system-message"); -} String.Format = function() { var s = arguments[0]; for (var i = 0; i < arguments.length - 1; i++) { @@ -28,18 +13,19 @@ String.Format = function() { } var getCounterData = function (btn) { - var row=jQuery(btn).parents("tr.counter_row"); - return { row: row }; + return { row: jQuery(btn).closest("tr.counter_row") }; } var handleJSONResponse = function (json, counter) { - updateMessages(json['messages'], "ordernumber"); - if (!json.authorized) { - alert(Joomla.JText._('PLG_ORDERNUMBER_JS_NOT_AUTHORIZED', "You are not authorized to modify order number counters.")); - } else if (json.error) { - alert(json.error); - } else { - // TODO: Which other error checks can we do? - } + if ('updateMessages' in ajax_ordernumber) { + ajax_ordernumber.updateMessages(json['messages'], "ordernumber"); + } + if (!json.authorized) { + alert(ajax_ordernumber.ORDERNUMBER_JS_NOT_AUTHORIZED); + } else if (json.error) { + alert(json.error); + } else { + // TODO: Which other error checks can we do? + } } var ajaxEditCounter = function (btn, nrtype, ctr, value) { var counter = getCounterData(btn); @@ -49,36 +35,43 @@ var ajaxEditCounter = function (btn, nrtype, ctr, value) { var value = NaN; var msgprefix = ""; while (isNaN(value) && (value != null)) { - var editprompt = Joomla.JText._('PLG_ORDERNUMBER_JS_EDITCOUNTER', "{0}Please enter the new value for the counter '{1}' (current value: {2}):"); + var editprompt = ajax_ordernumber.ORDERNUMBER_JS_EDITCOUNTER; value = prompt (String.Format(editprompt, msgprefix, counter.counter, counter.value), counter.value); if (value != null) value = parseInt(value); if (isNaN(value)) - msgprefix = Joomla.JText._('PLG_ORDERNUMBER_JS_INVALID_COUNTERVALUE', "You entered an invalid value for the counter.\n\n"); + msgprefix = ajax_ordernumber.ORDERNUMBER_JS_INVALID_COUNTERVALUE; } if (value != null) { - var loading = jQuery("img.vm-ordernumber-loading").first().clone().insertAfter(btn).show(); + var loading = jQuery("img.ordernumber-loading").first().clone().insertAfter(btn).show(); jQuery.ajax({ type: "POST", cache: false, dataType: "text", // Read text, but interpret as JSON later in the done method (prevents a warning!) - url: "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&action=setCounter&format=raw", - data: { nrtype: counter.type, counter: counter.counter, value: value }, + url: ajax_ordernumber.ajax_url, + data: { + action: 'setCounter', + nrtype: counter.type, + counter: counter.counter, + value: value + }, success: function( data ) { try { var json = jQuery.parseJSON(data); handleJSONResponse(json, counter); } catch (e) { - alert(Joomla.JText._('PLG_ORDERNUMBER_JS_JSONERROR')+"\n"+e); + alert(ajax_ordernumber.ORDERNUMBER_JS_JSONERROR+"\n"+e); return; } if (json.success>0) { - jQuery(counter.row).children(".counter_value").text(value); + // replace the whole row with the html returned by the AJAX call: + jQuery(counter.row).replaceWith(json.row); +// jQuery(counter.row).find(".counter_value").text(value); } else { - alert (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_MODIFY_FAILED', "Failed modifying counter {0}"), counter.counter)); + alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_MODIFY_FAILED, counter.counter)); } }, - error: function() { alert (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_MODIFY_FAILED', "Failed modifying counter {0}"), counter.counter)); }, + error: function() { alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_MODIFY_FAILED, counter.counter)); }, complete: function() { jQuery(loading).remove(); }, }); } @@ -88,63 +81,71 @@ var ajaxDeleteCounter = function (btn, nrtype, ctr, value) { counter.type=nrtype; counter.counter=ctr; counter.value=value; - var proceed = confirm (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_DELETECOUNTER', "Really delete counter '{0}' with value '{1}'?"), counter.counter, counter.value)); + var proceed = confirm (String.Format(ajax_ordernumber.ORDERNUMBER_JS_DELETECOUNTER, counter.counter, counter.value)); if (proceed == true) { - var loading = jQuery("img.vm-ordernumber-loading").first().clone().insertAfter(btn).show(); + var loading = jQuery("img.ordernumber-loading").first().clone().insertAfter(btn).show(); jQuery.ajax({ type: "POST", cache: false, dataType: "text", // Read text, but interpret as JSON later in the done method (prevents a warning!) - url: "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&action=deleteCounter&format=raw", - data: { nrtype: counter.type, counter: counter.counter }, + url: ajax_ordernumber.ajax_url, + data: { + action: 'deleteCounter', + nrtype: counter.type, + counter: counter.counter + }, success: function( data ) { try { var json = jQuery.parseJSON(data); handleJSONResponse(json, counter); } catch (e) { - alert(Joomla.JText._('PLG_ORDERNUMBER_JS_JSONERROR')+"\n"+e); + alert(ajax_ordernumber.ORDERNUMBER_JS_JSONERROR+"\n"+e); return; } if (json.success>0) { jQuery(counter.row).fadeOut(1500, function() { jQuery(counter.row).remove(); }); } else { - alert (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_DELETE_FAILED', "Failed deleting counter {0}"), counter.counter)); + alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_DELETE_FAILED, counter.counter)); } }, - error: function() { alert (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_DELETE_FAILED', "Failed deleting counter {0}"), counter.counter)); }, + error: function() { alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_DELETE_FAILED, counter.counter)); }, complete: function() { jQuery(loading).remove(); }, }); } } var ajaxAddCounter = function (btn, nrtype) { var row = jQuery(btn).parents("tr.addcounter_row"); - var countername = prompt (Joomla.JText._('PLG_ORDERNUMBER_JS_NEWCOUNTER', "Please enter the format/name of the new counter:")); + var countername = prompt (ajax_ordernumber.ORDERNUMBER_JS_NEWCOUNTER); if (countername != null) { - var loading = jQuery("img.vm-ordernumber-loading").first().clone().insertAfter(jQuery(btn).find("img.vmordernumber-counter-addbtn")).show(); + var loading = jQuery("img.ordernumber-loading").first().clone().insertAfter(jQuery(btn).find("img.ordernumber-counter-addbtn")).show(); jQuery.ajax({ type: "POST", cache: false, dataType: "text", // Read text, but interpret as JSON later in the done method (prevents a warning!) - url: "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&action=addCounter&format=raw", - data: { nrtype: nrtype, counter: countername }, + url: ajax_ordernumber.ajax_url, + data: { + action: "addCounter", + nrtype: nrtype, + counter: countername + }, success: function( data ) { var json = data ? jQuery.parseJSON(data) : null; try { var json = jQuery.parseJSON(data); handleJSONResponse(json, null); } catch (e) { - alert(Joomla.JText._('PLG_ORDERNUMBER_JS_JSONERROR')+"\n"+e); + alert(ajax_ordernumber.ORDERNUMBER_JS_JSONERROR+"\n"+e); return; } if (json.success>0) { - if (json.newrow) { - jQuery(row).before(jQuery(json.newrow)); + if (json.row) { + jQuery(row).before(jQuery(json.row)); } } else { - alert (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_ADD_FAILED', "Failed adding counter {0}"), countername)); + alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_ADD_FAILED, countername)); } }, - error: function() { alert (String.Format(Joomla.JText._('PLG_ORDERNUMBER_JS_ADD_FAILED', "Failed adding counter {0}"), countername)); }, + error: function() { alert (String.Format(ajax_ordernumber.ORDERNUMBER_JS_ADD_FAILED, countername)); }, complete: function() { jQuery(loading).remove(); }, }); } diff --git a/ordernumber_helper.php b/ordernumber_helper.php new file mode 100644 index 0000000000000000000000000000000000000000..49b407120d28e2c88d4d9b42b161b3a46da08daf --- /dev/null +++ b/ordernumber_helper.php @@ -0,0 +1,508 @@ +<?php +/** + * Advanced Ordernumbers generic helper class (e-commerce system agnostic) + * Reinhold Kainhofer, Open Tools, office@open-tools.net + * @copyright (C) 2012-2015 - Reinhold Kainhofer + * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html +**/ + +defined('_JEXEC') or die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' ) ; + +class OrdernumberHelper { + protected $_callbacks = array(); + public $_styles = array( + 'counter-table-class' => "table-striped", + 'counter-table-style' => "", + 'variable-table-class' => "", + 'variable-table-style' => "", + ); + /** + * An array containing all language keys for the translations used in the JavaScript code. + * Make sure to set those in the ajax_ordernumber JavaScript array! + */ + public $jstranslations = array( + "ORDERNUMBER_JS_NOT_AUTHORIZED", "ORDERNUMBER_JS_INVALID_COUNTERVALUE", "ORDERNUMBER_JS_JSONERROR", + "ORDERNUMBER_JS_NEWCOUNTER", "ORDERNUMBER_JS_EDITCOUNTER", "ORDERNUMBER_JS_DELETECOUNTER", + "ORDERNUMBER_JS_ADD_FAILED", "ORDERNUMBER_JS_MODIFY_FAILED", "ORDERNUMBER_JS_DELETE_FAILED", + ); + + /** + * The URL to call for AJAX calls + */ + public $ajax_url = ""; + + function __construct() { + // Set up + $this->registerCallback ("setupDateTimeReplacements", array($this, "setupDateTimeReplacements")); + } + + function getStyle($key) { + if (isset($this->_styles[$key])) { + return $this->_styles[$key]; + } else { + return ''; + } + } + /* Callback handling */ + + /** + * Register a callback for one of the known callback hooks. + * Valid callbacks are (together with their arguments): + * - translate($string) + * - getCounter($type, $countername, $default) + * - setCounter($type, $countername, $value) + * - setupDateTimeReplacements(&$reps, $details, $nrtype); + * - setupStoreReplacements(&$reps, $details, $nrtype); + * - setupOrderReplacements(&$reps, $details, $nrtype); + * - setupUserReplacements(&$reps, $details, $nrtype); + * - setupShippingReplacements(&$reps, $details, $nrtype); + * - setupThirdPartyReplacements(&$reps, $details, $nrtype); + + * - urlPath($path, $type) + * @param string $callback + * The name of the callback hook (string) + * @param function $func + * The function (usually a member of the plugin object) for the callback + * @return none + */ + public function registerCallback($callback, $func) { + $this->callbacks[$callback] = $func; + } + + public function __($string) { + if (isset($this->callbacks["translate"])) { + return $this->callbacks["translate"]($string); + } else { + return $string; + } + } + + public function urlPath($type, $file) { + if (isset($this->callbacks['urlPath'])) { + return $this->callbacks['urlPath']($type, $file); + } else { + throw new Exception('No callback defined for urlPath(type, file)!'); + } + } + + protected function replacementsCallback ($func, &$reps, $details, $nrtype) { + if (isset($this->callbacks[$func])) { + return $this->callbacks[$func]($reps, $details, $nrtype); + } + } + + protected function getCounter($type, $countername, $default) { + if (isset($this->callbacks['getCounter'])) { + return $this->callbacks['getCounter']($type, $countername, $default); + } else { + throw new Exception('No callback defined for getCounter(type, countername, default)!'); + } + } + + protected function setCounter($type, $countername, $value) { + if (isset($this->callbacks['getCounter'])) { + return $this->callbacks['getCounter']($type, $countername, $value); + } else { + throw new Exception('No callback defined for setCounter(type, countername, value)!'); + } + } + + /* Return a random "string" of the given length taken from the given alphabet */ + protected static function randomString($alphabet, $len) { + $alen = strlen($alphabet); + $r = ""; + for ($n=0; $n<$len; $n++) { + $r .= $alphabet[mt_rand(0, $alen-1)]; + } + return $r; + } + + protected function replaceRandom ($match) { + /* the regexp matches (random)(Type)(Len) as match, Type and Len is optional */ + $len = ($match[3]?$match[3]:1); + // Fallback: If no Type is given, use Digit + $alphabet = "0123456789"; + // Select the correct alphabet depending on Type + switch (strtolower($match[2])) { + case "digit": $alphabet = "0123456789"; break; + case "hex": $alphabet = "0123456789abcdef"; break; + case "letter": $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; break; + case "uletter": $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; break; + case "lletter": $alphabet = "abcdefghijklmnopqrstuvwxyz"; break; + case "alphanum": $alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; break; + } + return self::randomString ($alphabet, $len); + } + + protected function setupDateTimeReplacements (&$reps, $details, $nrtype) { + $utime = microtime(true); + $reps["[year]"] = date ("Y", $utime); + $reps["[year2]"] = date ("y", $utime); + $reps["[month]"] = date("m", $utime); + $reps["[day]"] = date("d", $utime); + $reps["[hour]"] = date("H", $utime); + $reps["[hour12]"] = date("h", $utime); + $reps["[ampm]"] = date("a", $utime); + $reps["[minute]"] = date("i", $utime); + $reps["[second]"] = date("s", $utime); + $milliseconds = (int)(1000*($utime - (int)$utime)); + $millisecondsstring = sprintf('%03d', $milliseconds); + $reps["[decisecond]"] = $millisecondsstring[0]; + $reps["[centisecond]"] = substr($millisecondsstring, 0, 2); + $reps["[millisecond]"] = $millisecondsstring; + } + + protected function setupReplacements($nrtype, $details) { + $reps = array(); + // The following callbacks directly modify the replacements! + $this->replacementsCallback("setupDateTimeReplacements", $reps, $details, $nrtype); + $this->replacementsCallback("setupStoreReplacements", $reps, $details, $nrtype); + $this->replacementsCallback("setupOrderReplacements", $reps, $details, $nrtype); + $this->replacementsCallback("setupUserReplacements", $reps, $details, $nrtype); + $this->replacementsCallback("setupShippingReplacements", $reps, $details, $nrtype); + $this->replacementsCallback("setupThirdPartyReplacements", $reps, $details, $nrtype); + return $reps; + } + + protected function setupCustomVariables ($nrtype, $order, $reps, $customvars) { + foreach ($customvars as $c) { + $conditionvar = strtolower($c['conditionvar']); + $op = $c['conditionop']; + + $found = false; + $match = false; + $compareval = null; + + if (isset($reps[$conditionvar])) { + $found = true; + $compareval = $reps[$conditionvar]; + } elseif (isset($reps['['.$conditionvar.']'])) { + $found = true; + $compareval = $reps['['.$conditionvar.']']; + }/* elseif ($order && $compareval = $order->getData($conditionvar)) { + // TODO: Handle order property + $found = true; + }*/ else { + // TODO: Handly other possible properties! + // TODO: Print out warning that variable could not be found. + } + if ($found) { + $condval = $c['conditionval']; + switch ($op) { + case 'nocondition': + $match = true; break; + case 'equals': + $match = ($compareval == $condval); break; + case 'contains': + if (is_array($compareval)) { + $match = in_array($condval, $compareval); + } else { + $match = strpos ($compareval, $condval); + } + break; + case 'smaller': + $match = ($compareval<$condval); break; + case 'smallerequal': + $match = ($compareval<=$condval); break; + case 'larger': + $match = ($compareval>$condval); break; + case 'largerequal': + $match = ($compareval>=$condval); break; + case 'startswith': + $match = (substr("$compareval", 0, strlen("$condval")) === "$condval"); break; + case 'endswith': + $match = (substr("$compareval", -strlen("$condval")) === "$condval"); break; + } + } elseif (empty($conditionvar)) { + $match = true; + } + if ($match) { + $varname = '['.strtolower($c['newvar']).']'; + $reps[$varname] = $c['newval']; + } + } + return $reps; + } + + // Allow the user to override the format like any other custom variable: + protected function setupNumberFormatString($fmt, $type, $order, $reps) { + if (isset($reps['['.$type.'_format]'])) { + return $reps['['.$type.'_format]']; + } else { + return $fmt; + } + } + + protected function doReplacements ($fmt, $reps) { + // First, replace all random...[n] fields. This needs to be done with a regexp and a callback: + $fmt = preg_replace_callback ('/\[(random)(.*?)([0-9]*?)\]/', array($this, 'replaceRandom'), $fmt); + // Only use string-valued variables for replacement (array-valued variables can be used in custom variable definitions!) + $reps = array_filter($reps, function($v) { return !is_array($v);} ); + return str_ireplace (array_keys($reps), array_values($reps), $fmt); + } + + protected function extractCounterSettings ($fmt, $type, $ctrsettings) { + // First, extract all counter settings, i.e. all strings of the form [#####:startval/increment] or [####/increment:startval] + $regexp = '%\[(#+)(/([0-9]+))?(:([0-9]+))?(/([0-9]+))?\]%'; + + if (preg_match($regexp, $fmt, $counters)) { + // $counters is an array of the form: + // Array ( + // [0] => [#####:100/3] + // [1] => ##### + // [2] => + // [3] => + // [4] => :100 + // [5] => 100 + // [6] => /3 + // [7] => 3 + // ) + $ctrsettings["${type}_padding"] = strlen($counters[1]); + if (!empty($counters[2])) { + // $counters[2] contains the whole "/n" part, while $counters[3] contains just the step itself + $ctrsettings["${type}_step"] = $counters[3]; + } + if (!empty($counters[4])) { + // $counters[4] contains the whole ":n" part, while $counters[5] contains just the start value itself + $ctrsettings["${type}_start"] = $counters[5]; + } + + if (!empty($counters[6])) { + // $counters[6] contains the whole ":n" part, while $counters[7] contains just the start value itself + $ctrsettings["${type}_step"] = $counters[7]; + } + + $fmt = preg_replace($regexp, "#", $fmt); + } + // Split at a | to get the number format and a possibly different counter increment format + // If a separate counter format is given after the |, use it, otherwise reuse the number format itself as counter format + $parts = explode ("|", $fmt); + $ctrsettings["${type}_format"] = $parts[0]; + $ctrsettings["${type}_counter"] = ($ctrsettings["${type}_global"]=='yes')?"":$parts[(count($parts)>1)?1:0]; + + return $ctrsettings; + } + + /** + * Create a number of given type for the given format. Optionally, custom variable definitions and counter formatting can be passed. + * @param fmt The Format of the number (containing variables as [variable] and the counter as # or [####:initial/step]) + * @param type The type of the number format, typically order_number, invoice_number, etc. (depending on the e-commerce suite) + * @param order The e-commerce-suite specific object describing the order. This will simply be passed on to the replacement hooks function for further data extraction during variable setup + * @param customvars Definitions (conditions and values) for custom variables. An array of arrays with keys conditionvar, conditionop, conditionval, newvar, newval + * @param ctrsettings Counter formatting defaults (will be overridden by an explicit counter formating variable of [####:initial/step] in the format). Array keys are: $type_format, $type_counter, $type_global, $type_padding, $type_step, $type_start + * @return A new number for the given format. The incremented counter has been properly stored. + */ + public function createNumber ($fmt, $type, $order, $customvars, $ctrsettings) { + $reps = $this->setupReplacements ($type, $order); + $reps = $this->setupCustomVariables ($type, $order, $reps, $customvars); + $format = $this->setupNumberFormatString($fmt, $type, $order, $reps); + $format = $this->doReplacements($format, $reps); + $ctrsettings = $this->extractCounterSettings ($format, $type, $ctrsettings); + +// JFactory::getApplication()->enqueueMessage("<pre>Replacements for $type:".print_r($reps,1)."</pre>", 'error'); + // Increment the counter only if the format contains a placeholder for it! + if (strpos($ctrsettings["${type}_format"], "#") !== false) { + $countername = $ctrsettings["${type}_counter"]; + // Look up the current counter + $count = $this->getCounter($type, $countername, $ctrsettings["${type}_start"] - $ctrsettings["${type}_step"]) + $ctrsettings["${type}_step"]; + $this->setCounter($type, $countername, $count); + // return the format with the counter inserted + $number = str_replace ("#", sprintf('%0' . $ctrsettings["${type}_padding"] . 's', $count), $ctrsettings["${type}_format"]); + } else { + $number = $ctrsettings["${type}_format"]; + } + return $number; + } + + + /** + * Create the counter modification HTML table + * @param $type string + * + * @param + */ + public function counter_modification_create_table($type, $counters) { +/* $pluginpath = '/plugins/shopper/ordernumber/ordernumber/'; + $doc = JFactory::getDocument()->addStyleSheet(JURI::root(true) . $pluginpath . 'assets/css/ordernumber.css'); + $this->makeJSTranslationsAvailable(); + $this->loadjQuery(); + $doc->addScript(JURI::root(true).$pluginpath . 'assets/js/ordernumber.js'); + + // Look up the current counters + $db = JFactory::getDBO(); + $db->setQuery('SELECT `number_format`, `count` FROM `#__virtuemart_shopper_plg_ordernumber` WHERE `number_type`='.$db->quote($type) . ' ORDER BY `number_format`;' ); + $counters = $db->loadObjectList(); + // Joomla 2.x uses <li> for the params and float:left on the controls, so we need to add that too + $float = ""; + if (version_compare(JVERSION, '3.0', 'lt')) { + $float = "float: left; "; + } +*/ + $html=array(); + $html[] = "<img src='" . $this->urlPath ('images', 'loading.gif') . "' class='ordernumber-loading' style=\"display: none; position: absolute; top: 2px; left: 0px; z-index: 9999;\"/>"; + $html[] = "<table class=\"ordernumber-countertable " . $this->getStyle('counter-table-class') . "\" " . $this->getStyle('counter-table-style') . ">"; + $html[] = " <tr>"; + $html[] = " <th class='counter_format'>" . $this->__ ('PLG_ORDERNUMBER_COUNTERLIST_HEADER_COUNTER')."</th>"; + $html[] = " <th class='counter_value'>" . $this->__ ('PLG_ORDERNUMBER_COUNTERLIST_HEADER_VALUE'). "</th>"; + $html[] = " <th class='counter_buttons'></th>"; + $html[] = " </tr>"; + $html[] = " <colgroup><col class='counter_type'><col style=\"text-align: center\" ><col ></colgroup>"; + foreach ($counters as $c) { + $html[] = $this->counter_modification_create_row ($type, $c->number_format, $c->count); + } + $html[] = " <tr class='addcounter_row'>"; + $html[] = " <td colspan=3 class='counter_add'>"; + $html[] = " <div class='ordernumber-counter-addbtn ordernumber-btn' onClick='ajaxAddCounter(this, " . json_encode($type).")'>"; + $html[] = " <div class='ordernumber-ajax-loading'>"; + $html[] = " <img src='" . $this->urlPath('images', 'icon-16-new.png') . "' class='ordernumber-counter-addbtn' />"; + $html[] = " </div>" . $this->__('PLG_ORDERNUMBER_COUNTERLIST_ADD'); + $html[] = " </div>"; + $html[] = " </td>"; + $html[] = " </tr>"; + $html[] = "</table>"; + return implode("\n", $html); + } + + public function counter_modification_create_row ($type, $counter, $value) { + $html=array(); + $html[] = " <tr class='counter_row counter_row_$type'>"; + $html[] = " <td class='counter_format'>" . (string)(($counter=="")?($this->__ ('PLG_ORDERNUMBER_COUNTERLIST_GLOBAL')):$counter) . "</td>"; + $html[] = " <td class='counter_value'>" . (string)$value . "</td>"; + $html[] = " <td class='counter_buttons'>"; + $html[] = " <div class='ordernumber-ajax-loading'>"; + $html[] = " <img src='" . $this->urlPath('images', 'icon-16-edit.png') . "' class='ordernumber-counter-editbtn ordernumber-btn' "; + $html[] = " onClick='ajaxEditCounter(this, " . json_encode($type) . ", ".json_encode($counter).", $value)' />"; + $html[] = " </div>"; + $html[] = " <div class='ordernumber-ajax-loading'>"; + $html[] = " <img src='" . $this->urlPath ('images', 'icon-16-delete.png') . "' class='ordernumber-counter-deletebtn ordernumber-btn' "; + $html[] = " onClick='ajaxDeleteCounter(this, ".json_encode($type).", ".json_encode($counter).", $value)' />"; + $html[] = " </div>"; + $html[] = " </td>"; + $html[] = " </tr>"; + return implode("\n", $html); + } + + /** + * Create the html table (with AJAX) to define and modify custom variable definitions. + * The returned HTML code assumes that the caller properly adds the ordernumber.css + * and ordernumber.js to the page and loads the jQuery library. + * @param name string + * The HTML post/request variable name for the control. + * @param variables array + * The current list of custom variable replacements + * + * @retval string + * The HTML code for the custom variable definition table. + */ + public function custom_variables_create_table($name, $variables) { + $html=array(); +// $html[] = "<pre>Variables: ".print_r($variables,1)."</pre>"; + $html[] = '<table id="ordernumber_variables_template" style="display:none">'; + $html[] = $this->custom_variables_create_row($name, array(), 'disabled'); + $html[] = '</table>'; + + $html[] = '<table id="ordernumber_variables" class="ordernumber_variables ' . $this->getStyle('variable-table-class') . '" cellspacing="0" ' . $this->getStyle('variable-table-style') . '>'; + $columns = array( + 'variables_ifvar' => $this->__('PLG_ORDERNUMBER_REPL_IFVAR'), + 'variables_ifop' => '', + 'variables_ifval' => $this->__('PLG_ORDERNUMBER_REPL_IFVAL'), + 'variables_then' => $this->__(''), + 'variables_thenvar' => $this->__('PLG_ORDERNUMBER_REPL_SETVAR'), + 'variables_thenval' => $this->__('PLG_ORDERNUMBER_REPL_TOVAL'), + 'sort' => '', + 'variables_settings' => '', + ); + $html[] = ' <thead>'; + $html[] = ' <tr class="ordernumber_variables_header">'; + foreach ( $columns as $key => $column ) { + $html[] = '<th class="' . $key . '">' . htmlspecialchars( $column ) . '</th>'; + } + $html[] = ' </tr>'; + $html[] = ' <tr id="ordernumber-replacements-empty-row" class="oton-empty-row-notice ' . (empty($variables)?"":"rowhidden") . '">'; + $html[] = ' <td class="oton-empty-row-notice" colspan="8">'; + $html[] = ' <em>' . $this->__('PLG_ORDERNUMBER_REPL_NOCUSTOMVARS') . '</em>'; + $html[] = ' <input type="hidden" name="' . $name . '" value="" ' . (empty($variables))?'':'disabled' . '>'; + $html[] = ' </td>'; + $html[] = ' </tr>'; + $html[] = ' </thead>'; + $html[] = ' <colgroup>'; + foreach ($columns as $key => $column) { + $html[] = '<col class="' . $key . '" />'; + } + $html[] = ' </colgroup>'; + $html[] = ''; + $html[] = ' <tbody>'; + foreach ($variables as $var) { + $html[] = $this->custom_variables_create_row($name, $var); + } + $html[] = ' </tbody>'; + $html[] = ' <tfoot>'; + $html[] = ' <tr class="addreplacement_row">'; + $html[] = ' <td colspan=8 class="variable_add">'; + $html[] = ' <div class="ordernumber-variables-addbtn ordernumber-btn" onClick="ordernumberVariablesAddRow(\'ordernumber_variables_template\', \'ordernumber_variables\')">'; + $html[] = ' <div class="ordernumber-ajax-loading"><img src="' . $this->urlPath('images', 'icon-16-new.png' ) . '" class="ordernumber-counter-addbtn" /></div>'; + $html[] = $this->__('PLG_ORDERNUMBER_REPL_ADDVAR'); + $html[] = ' </div>'; + $html[] = ' </td>'; + $html[] = ' </tr>'; + $html[] = ' </tfoot>'; + $html[] = '</table>'; + return implode("\n", $html); + } + + public function custom_variables_create_row($name, $values = array(), $disabled = '') { + $operator = (isset($values['conditionop'])?$values['conditionop']:''); + $operators = array( + 'nocondition' => $this->__('PLG_ORDERNUMBER_REPL_OP_NOCOND'), + 'equals' => '=', + 'contains' => $this->__('PLG_ORDERNUMBER_REPL_OP_CONTAINS'), + 'smaller' => '<', + 'smallerequal' => '<=', + 'larger' => '>', + 'largerequal' => '>=', + 'startswith' => $this->__('PLG_ORDERNUMBER_REPL_OP_STARTS'), + 'endswith' => $this->__('PLG_ORDERNUMBER_REPL_OP_ENDS'), + ); + $html = ' + <tr> + <td class="variables_ifvar"><input name="' . $name . '[conditionvar][]" value="' . (isset($values['conditionvar'])?$values['conditionvar']:'') . '" ' . $disabled . '/></td> + <td class="variables_ifop" ><select name="' . $name . '[conditionop][]" ' . $disabled . ' style="width: 100px">'; + foreach ($operators as $op => $opname) { + $html .= ' <option value="' . $op . '" ' . (($op === $operator)?'selected':'') . '>' . htmlspecialchars($opname) . '</option>'; + } + $html .= '</select></td> + <td class="variables_ifval" ><input name="' . $name . '[conditionval][]" value="' . (isset($values['conditionval'])?$values['conditionval']:'') . '" ' . $disabled . '/></td> + <td class="variables_then">=></td> + <td class="variables_thenvar"><input name="' . $name . '[newvar][]" value="' . (isset($values['newvar'])?$values['newvar']:'') . '" ' . $disabled . '/></td> + <td class="variables_thenval"><input name="' . $name . '[newval][]" value="' . (isset($values['newval'])?$values['newval']:'') . '" ' . $disabled . '/></td> + <td class="sort"></td> + <td class="variables_settings"><img src="' . $this->urlPath('images', 'icon-16-delete.png' ) . '" class="ordernumber-replacement-deletebtn ordernumber-btn"></td> + </tr>'; + return $html; + } + + /** + * Modify the json that contains JavaScript setup code to be used by ordernumber.js + */ + function addCustomJS(&$json) {} + function appendJS() {} + function createJSSetup() { + static $done = 0; // <= prevent double js code + $json = array(); + $json['ajax_url'] = $this->ajax_url; + + foreach ($this->jstranslations as $key) { + $json[$key] = $this->__($key); + } + $this->addCustomJS($json); + $js='/* <![CDATA[ */ +var ajax_ordernumber = ' . json_encode($json) . '; +'; + $js .= $this->appendJS(); + $js .= '/* ]]> */ +'; + $done = 1; + return $js; + } + +} diff --git a/ordernumber_helper_joomla.php b/ordernumber_helper_joomla.php new file mode 100644 index 0000000000000000000000000000000000000000..c0152977edba724146434eb08fa83c8f6283b0c3 --- /dev/null +++ b/ordernumber_helper_joomla.php @@ -0,0 +1,178 @@ +<?php +/** + * Advanced Ordernumbers generic helper class (e-commerce system agnostic) + * Reinhold Kainhofer, Open Tools, office@open-tools.net + * @copyright (C) 2012-2015 - Reinhold Kainhofer + * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html +**/ + +defined('_JEXEC') or die( 'Direct Access to ' . basename( __FILE__ ) . ' is not allowed.' ) ; + +if (!class_exists( 'VmConfig' )) + require(JPATH_ROOT.DS.'administrator'.DS.'components'.DS.'com_virtuemart'.DS.'helpers'.DS.'config.php'); +VmConfig::loadConfig(); + +if (!class_exists( 'OrdernumberHelper' )) + require_once (dirname(__FILE__) . DS . 'ordernumber_helper.php'); + +class OrdernumberHelperJoomla extends OrdernumberHelper { + public $tableName = ''; + + function __construct() { + parent::__construct(); + // Joomla-specific Defaults for the HTML tables + $this->_styles['counter-table-class'] = "table-striped"; + + $this->ajax_url = "index.php?option=com_virtuemart&view=plugin&type=vmshopper&name=ordernumber&format=raw"; + + // Joomla 2.x uses <li> for the params and float:left on the controls, so we need to add that too + if (version_compare(JVERSION, '3.0', 'lt')) { + $this->_styles['counter-table-style'] = "style=\"float: left;\""; + } + + } + + static function getHelper() { + static $helper = null; + if (!$helper) { + $helper = new OrdernumberHelperJoomla(); + } + return $helper; + } + + // VM2 on J2 works, VM3 on J3 works out of the box, but + // VM3 on J2 does NOT work by simply calling vmJsApi::jQuery, because + // the JS is never added to the page header, so we have to add this manually + public function loadjQuery() { + vmJsApi::jQuery(); + // TODO: jquery::ui available only in J3: + if (version_compare(JVERSION, '3.0', 'lt')) { + } else { + JHtml::_('jquery.ui', array('core', 'sortable')); + } + // If we are on Joomla 2.5 and VM 3, manually add the script declarations + // cached in vmJsApi to the document header: + if (version_compare(JVERSION, '3.0', 'lt') && defined('VM_VERSION') && VM_VERSION>=3) { + $document = JFactory::getDocument(); + $scripts = vmJsApi::getJScripts(); + foreach ($scripts as $name => $jsToAdd) { + if($jsToAdd['written']) continue; + $file = $jsToAdd['script'] ? $jsToAdd['script'] : $name; + + if(strpos($file,'/')!==0){ + $file = vmJsApi::setPath($file,false,''); + } else if(strpos($file,'//')!==0){ + $file = JURI::root(true).$file; + } + + $ver = ''; + if(!empty($jsToAdd['ver'])) $ver = '?vmver='.$jsToAdd['ver']; + $document->addScript( $file .$ver,"text/javascript",$jsToAdd['defer'],$jsToAdd['async'] ); + vmJsApi::removeJScript($name); + } + } + } + + + public static function transposeCustomVariables($cvar) { + if (is_object($cvar)) + $cvar = (array)$cvar; + if (!is_array($cvar)) + $cvar = array(); + // The customvars are stored in transposed form (for technical reasons, since there is no trigger + // called when the corresponding form field from the plugin param is saved) + $customvars = array(); + + if (!empty($cvar)) { + $keys = array_keys($cvar); + foreach (array_keys($cvar[$keys[0]]) as $i) { + $entry = array(); + foreach ($keys as $k) { + $entry[$k] = $cvar[$k][$i]; + } + $customvars[] = $entry; + } + } + return $customvars; + } + + public function __($string) { +// print("<pre>translating: $string</pre>"); + return JText::_($string); + } + function urlPath($type, $file) { + static $pluginpath = '/plugins/vmshopper/ordernumber/ordernumber/'; + return JURI::root(true) . $pluginpath . 'assets/' . $type . '/' . $file; + } + + function getCounter($nrtype, $format, $default=0) { + $db = JFactory::getDBO(); + + /* prevent sql injection attacks by escaping the user-entered format! Empty for global counter... */ + /* For global counting, simply read the empty number_format entries! */ + $q = 'SELECT `count` FROM `'.$this->tableName.'` WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); + $db->setQuery($q); + $existing = $db->loadResult(); + $count = $existing?$existing:$default; + return $count; + } + + function counterExists($nrtype, $format) { + $db = JFactory::getDBO(); + $q = 'SELECT `count` FROM `'.$this->tableName.'` WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); + $db->setQuery($q); + return ($db->loadResult() != null); + } + + // Insert new counter value into the db + function addCounter($nrtype, $format, $value) { + $db = JFactory::getDBO(); + $q = 'INSERT INTO `'.$this->tableName.'` (`count`, `number_type`, `number_format`) VALUES ('.(int)$value.','.$db->quote($nrtype).', '.$db->quote($format).')'; + $db->setQuery( $q ); + $db->query(); + return $db->getAffectedRows(); + } + + // Insert new counter value into the db or update existing one + function setCounter($nrtype, $format, $value) { + $db = JFactory::getDBO(); + $q = 'UPDATE `'.$this->tableName.'` SET `count`= "'.(int)$value.'" WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); + $db->setQuery( $q ); + $db->query(); + if ($db->getAffectedRows()<1) { + return $this->addCounter($nrtype, $format, $value); + } else { + return $db->getAffectedRows(); + } + } + + // Insert new counter value into the db or update existing one + function deleteCounter($nrtype, $format) { + $db = JFactory::getDBO(); + $format = $db->escape ($format); + $q = 'DELETE FROM `'.$this->tableName.'` WHERE `number_type`='.$db->quote($nrtype).' AND `number_format`='.$db->quote($format); + $db->setQuery( $q ); + $db->query(); + return $db->getAffectedRows(); + } + + function appendJS() { + // Extract the messages from the returned string, add the ordernumber-message class (so the next ajax call + // can remove them again) and then move the messages to the original message container. + // Things are complicated by the fact that no #system-message element exists if no messages were printed so far + return 'ajax_ordernumber.updateMessages = function(messages, area) { + jQuery( "#system-message-container #system-message ."+area+"-message").remove(); + var newmessages = jQuery( messages ).find("div.alert, .message").addClass(area+"-message"); + if (!jQuery( "#system-message-container #system-message").length && newmessages.length) { + if (jQuery(newmessages).first().prop("tagName")=="dt") { // Joomla 2.x: + jQuery( "#system-message-container" ).append( "<dl id=\'system-message\'></div>" ); + } else { + jQuery( "#system-message-container" ).append( "<div id=\'system-message\'></div>" ); + } + } + newmessages.appendTo( "#system-message-container #system-message"); +}'; + } + + +}