Explorar el Código

Merge branch 'master' of https://github.com/unaio/una

AntonLV hace 4 años
padre
commit
d7e8fdfb6e

+ 1 - 1
inc/version.inc.php

@@ -7,6 +7,6 @@
  * @{
  */
 
-define('BX_DOL_VERSION', '13.0.0-DEV1'); ///< system files version, for DB version @see bx_get_ver, DB and files version must match
+define('BX_DOL_VERSION', '13.0.0-A2'); ///< system files version, for DB version @see bx_get_ver, DB and files version must match
 
 /** @} */

+ 1 - 1
install/index.php

@@ -10,7 +10,7 @@
 define ('BX_DOL_INSTALL',  true);
 define ('BX_SKIP_INSTALL_CHECK', true);
 
-define ('BX_DOL_VER', '13.0.0-A1');
+define ('BX_DOL_VER', '13.0.0-A2');
 
 define ('BX_INSTALL_DEFAULT_LANGUAGE', 'en');
 

+ 48 - 1
modules/boonex/artificer/data/template/system/css/editor.less

@@ -1,2 +1,49 @@
 @import 'default.less';
-@import '../../../../../../../template/css/editor.less';
+@import '../../../../../../../template/css/editor.less';
+
+
+.bx-artificer .ql-container.ql-snow{
+    border-radius: 0 0 0.375rem 0.375rem;
+}
+.bx-artificer .ql-toolbar{
+    border-radius: 0.375rem 0.375rem 0 0;
+}
+.bx-artificer .ql-editor{
+    border-radius: 0 0 0.375rem 0.375rem;
+    background: #fff;
+}
+.bx-artificer .bx-form-input-html-quill-empty .ql-editor{
+    border-radius: 0.375rem;
+    min-height: 150px;
+}
+.bx-artificer .bx-form-input-html-quill-empty.ql-container.ql-snow{
+    border-radius: 0.375rem;
+}
+@media (prefers-color-scheme: dark) {
+	.bx-artificer .ql-stroke{
+		stroke: rgb(209, 213, 219) !important;
+	}
+	.bx-artificer .ql-fill{
+		fill: rgb(209, 213, 219) !important;
+	}
+	.bx-artificer .ql-picker{
+		color: rgb(209, 213, 219) !important;
+	}
+	.bx-artificer .ql-toolbar{
+        border-color: rgba(55,65,81,1) !important;
+	}
+    .bx-artificer .ql-container.ql-snow{
+        border-color: rgba(55,65,81,1) !important;
+    }
+	.bx-artificer .ql-editor{
+		background: rgb(17, 24, 39);
+		color: rgb(209, 213, 219);
+	}
+	.bx-artificer .ql-editor.ql-blank::before{
+	    color: rgba(255,255,255,0.6);
+	}
+    .bx-artificer .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{
+        background: rgb(17, 24, 39);
+		color: rgb(209, 213, 219);
+    }
+}

+ 11 - 1
modules/boonex/decorous/data/template/system/css/editor.less

@@ -1,2 +1,12 @@
 @import 'default.less';
-@import '../../../../../../../template/css/editor.less';
+@import '../../../../../../../template/css/editor.less';
+
+// quill style
+.ql-toolbar.ql-snow{
+    border-radius: 0 !important;
+}
+.ql-toolbar.ql-snow,
+.ql-container.ql-snow{
+     border-color: #d9d9d9 !important; 
+}
+

+ 6 - 1
modules/boonex/lucid/data/template/system/css/editor.less

@@ -1,2 +1,7 @@
 @import 'default.less';
-@import '../../../../../../../template/css/editor.less';
+@import '../../../../../../../template/css/editor.less';
+
+.ql-toolbar.ql-snow{
+    border: none !important;
+    border-bottom: 1px solid rgba(50, 100, 180, 0.2) !important;
+}

+ 12 - 1
modules/boonex/ocean/data/template/system/css/editor.less

@@ -1,2 +1,13 @@
 @import 'default.less';
-@import '../../../../../../../template/css/editor.less';
+@import '../../../../../../../template/css/editor.less';
+
+.ql-toolbar.ql-snow{
+    border-radius: 0.3rem 0.3rem 0 0 !important;
+}
+.ql-toolbar.ql-snow,
+.ql-container.ql-snow{
+    border-color: #6097b0 !important; 
+    border-width:2px !important;
+}
+
+

+ 5 - 1
modules/boonex/protean/data/template/system/css/editor.less

@@ -1,2 +1,6 @@
 @import 'default.less';
-@import '../../../../../../../template/css/editor.less';
+@import '../../../../../../../template/css/editor.less';
+
+.ql-toolbar.ql-snow, .ql-container{
+    border-color:rgba(136, 153, 170, 0.3) !important;
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
modules/boonex/protean/install/sql/install.sql


+ 4 - 45
template/css/editor.quill.css

@@ -4,50 +4,9 @@
 .ql-picker-options{
     z-index: 2 !important;
 }
-.ql-editor{
-    background: #fff;
-}    
-.bx-artificer .ql-container.ql-snow{
-    border-radius: 0 0 0.375rem 0.375rem;
+.ql-toolbar{
+    border-radius: 0.3rem 0.3rem 0 0;
 }
-.bx-artificer .ql-toolbar{
-    border-radius: 0.375rem 0.375rem 0 0;
-}
-.bx-artificer .ql-editor{
-    border-radius: 0 0 0.375rem 0.375rem;
-}
-.bx-artificer .bx-form-input-html-quill-empty .ql-editor{
-    border-radius: 0.375rem;
-    min-height: 150px;
-}
-.bx-artificer .bx-form-input-html-quill-empty.ql-container.ql-snow{
-    border-radius: 0.375rem;
-}
-@media (prefers-color-scheme: dark) {
-	.bx-artificer .ql-stroke{
-		stroke: rgb(209, 213, 219) !important;
-	}
-	.bx-artificer .ql-fill{
-		fill: rgb(209, 213, 219) !important;
-	}
-	.bx-artificer .ql-picker{
-		color: rgb(209, 213, 219) !important;
-	}
-	.bx-artificer .ql-toolbar{
-        border-color: rgba(55,65,81,1) !important;
-	}
-    .bx-artificer .ql-container.ql-snow{
-        border-color: rgba(55,65,81,1) !important;
-    }
-	.bx-artificer .ql-editor{
-		background: rgb(17, 24, 39);
-		color: rgb(209, 213, 219);
-	}
-	.bx-artificer .ql-editor.ql-blank::before{
-	    color: rgba(255,255,255,0.6);
-	}
-    .bx-artificer .ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options{
-        background: rgb(17, 24, 39);
-		color: rgb(209, 213, 219);
-    }
+.ql-container.ql-snow{
+    border-radius: 0 0 0.3rem 0.3rem;
 }

+ 9 - 10
template/scripts/BxBaseEditorQuill.php

@@ -86,12 +86,6 @@ class BxBaseEditorQuill extends BxDolEditor
             $sToolbarItems = $this->_sButtonsCustom;
         }
         
-        $sCss = 'editor.less';
-        $aCss = BxDolTemplate::getInstance()->_lessCss(array(
-        	'path' => $this->_oTemplate->getCssPath($sCss),
-        	'url' => $this->_oTemplate->getCssUrl($sCss)
-        ));
-        
         $sEditorName = 'quill_' . str_replace(['-', ' '], '_', $aAttrs['form_id'] . '_' . $aAttrs['element_name']);
         $this->_oTemplate->addJsTranslation([
             '_sys_txt_quill_tooltip_bold',
@@ -127,8 +121,7 @@ class BxBaseEditorQuill extends BxDolEditor
             'bx_var_element_name' => str_replace(['-', ' '], '_', $aAttrs['element_name']),
             'bx_var_editor_name' => $sEditorName,
             'bx_var_skin' => bx_js_string($this->_aObject['skin'], BX_ESCAPE_STR_APOS),
-            'bx_url_root' => bx_js_string(BX_DOL_URL_ROOT, BX_ESCAPE_STR_APOS),
-            'bx_var_css_path' => bx_js_string($aCss['url'], BX_ESCAPE_STR_APOS),
+            'bx_url_root' => bx_js_string(BX_DOL_URL_ROOT, BX_ESCAPE_STR_APOS)
         ));
 
         if ($bDynamicMode) {
@@ -205,13 +198,19 @@ class BxBaseEditorQuill extends BxDolEditor
             $sJsPrefixRoot  . $sJsSuffix . 'editor.quill.js',
         );
 
-        $aCss = array(
+        $sCss = 'editor.less';
+        $aCss = BxDolTemplate::getInstance()->_lessCss(array(
+        	'path' => $this->_oTemplate->getCssPath($sCss),
+        	'url' => $this->_oTemplate->getCssUrl($sCss)
+        ));
+        
+        $aCss = array_merge($aCss, array(
             BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'quill/|quill.' . $this->_aObject['skin'] . '.css',  
             BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'quill/|quill.mention.css', 
             BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'highlight/|default.min.css',
             BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'quill/quill.imageUploader.min.css',
             BX_DIRECTORY_PATH_BASE . 'css/|editor.quill.css',
-        );
+        ));
 
         return array($aJs, $aCss);
     }

+ 6 - 6
upgrade/files/12.1.0-13.0.0.A1/files_delete.php

@@ -36,12 +36,12 @@ $aFilesDelete = array(
 	'plugins/paypal/composer',
 	'plugins/paypal/paypal',
 	'plugins/paypal/autoload.php',
-	'plugins/phpmailer/Exception.php',
-	'plugins/phpmailer/LICENSE',
-	'plugins/phpmailer/PHPMailer.php',
-	'plugins/phpmailer/README.md',
-	'plugins/phpmailer/SMTP.php',
-	'plugins/phpmailer/VERSION',
+//	'plugins/phpmailer/Exception.php',
+//	'plugins/phpmailer/LICENSE',
+//	'plugins/phpmailer/PHPMailer.php',
+//	'plugins/phpmailer/README.md',
+//	'plugins/phpmailer/SMTP.php',
+//	'plugins/phpmailer/VERSION',
 	'plugins/recaptcha',
 	'plugins/recurly/recurly',
 	'plugins/recurly/LICENSE',

+ 9 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/check.php

@@ -0,0 +1,9 @@
+<?php
+
+$mixCheckResult = 'Update can not be applied';
+
+$sVer = $this->oDb->getOne("SELECT `version` FROM `sys_modules` WHERE `name` = 'system'");
+if ('13.0.0.A1' == $sVer || '13.0.0-A1' == $sVer)
+    $mixCheckResult = true;
+
+return $mixCheckResult;

+ 274 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/inc/js/editor.quill.js

@@ -0,0 +1,274 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+function bx_editor_init(oEditor, oParams){
+    hljs.configure({   
+        languages: ['javascript', 'php', 'html', 'css']
+    });
+    if (oParams.toolbar){
+        oParams.toolbar = {
+            container: oParams.toolbar,
+                handlers: {
+                'embed': function(value) {
+                    bx_prompt(_t('_sys_txt_quill_tooltip_embed_popup_header'), '', function(oPopup){
+                        sLink = $(oPopup).find("input[type = 'text']").val()
+                        $.getJSON(oParams.root_url + 'embed.php?', {a: 'get_link', l: sLink}, function(aData){
+                            oEditor.insertEmbed(100, 'embed-link', {source: sLink, inlinecode : aData.code});
+                            if ($(oParams.selector).next().next().find('.bx-embed-link a[href="' + aData.link + '"]').length > 0)
+                                bx_embed_link($(oParams.selector).next().next().find('.bx-embed-link a[href="' + aData.link + '"]')[0]);
+                            else
+                                bx_embed_link();
+                        });
+                    });
+                },
+                'link': function(value) {
+                    if (value) {
+                        bx_prompt(_t('_sys_txt_quill_tooltip_link_popup_header'), '', function(oPopup){
+                            oEditor.format('link', $(oPopup).find("input[type = 'text']").val());
+                        });
+                    } else {
+                        oEditor.format('link', false);
+                    }
+                }
+            }
+        }
+    }
+    $(oParams.selector).after("<div id='" + oParams.name + "' class='bx-def-font-inputs bx-form-input-textarea bx-form-input-html bx-form-input-html-quill " + oParams.css_class + "'>" + $(oParams.selector).val() + "</div>" );
+    $(oParams.selector).hide();
+    
+    $(oParams.selector).attr('object_editor', oParams.name);
+                
+    if (typeof bQuillRegistred === 'undefined' && oParams.toolbar) {
+        
+        var Embed = Quill.import('blots/embed');
+        
+        class MenthionLink extends Embed {
+            static create(value) {
+                let node = super.create(value);
+                if (value.id && value.value){
+                    node.setAttribute('href', value.id);
+                    node.innerHTML = '@' + value.value;
+                    node.setAttribute('title', '@' + value.value);
+                }
+                return node;
+            }
+            
+            format(name, value) {
+                if (name === 'href' || name === 'title') {
+                    if (value) {
+                        this.domNode.setAttribute(name, value);
+                        if (name === 'title'){
+                            this.domNode.innerHTML = value;
+                        }
+                    } else {
+                        this.domNode.removeAttribute(name, value);
+                    }
+                } 
+                else {
+                    super.format(name, value);
+                }
+            };
+                
+            static formats(node) {
+                let format = {};
+                if (node.hasAttribute('href')) {
+                    format.href = node.getAttribute('href');
+                }
+                if (node.hasAttribute('title')) {
+                    format.title = node.getAttribute('title');
+                }
+                return format;
+            }  
+            
+        }
+        MenthionLink.blotName = 'menthion-link'; 
+        MenthionLink.className = 'bx-menthion-link';
+        MenthionLink.tagName = 'a';                
+        Quill.register({
+            'formats/menthion-link': MenthionLink
+        });
+        
+        class EmbedCode extends Embed {
+            static create(value) {
+                let node = super.create(value);
+                if (value.source && value.inlinecode){
+                    node.setAttribute('source', value.source);
+                    node.innerHTML = value.inlinecode;
+                    return node;
+                }
+                return node;
+            };
+           
+            format(name, value) {
+                if (name === 'source') {
+                    if (value) {
+                        this.domNode.setAttribute(name, value);
+                    } else {
+                        this.domNode.removeAttribute(name, value);
+                    }
+                } 
+                else {
+                    super.format(name, value);
+                }
+            };
+                
+            static formats(node) {
+                let format = {};
+                if (node.hasAttribute('source')) {
+                  format.source = node.getAttribute('source');
+                }
+                return format;
+            }    
+        }
+        EmbedCode.className = 'bx-embed-link';
+        EmbedCode.blotName = 'embed-link'; 
+        EmbedCode.tagName = 'div';                
+        Quill.register({
+            'formats/embed-link': EmbedCode
+        });
+        
+        
+        
+        bQuillRegistred = true; 
+        
+        var icons = Quill.import('ui/icons');
+        icons['embed'] = '<svg class="fr-svg" focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M20.73889,15.45929a3.4768,3.4768,0,0,0-5.45965-.28662L9.5661,12.50861a3.49811,3.49811,0,0,0-.00873-1.01331l5.72174-2.66809a3.55783,3.55783,0,1,0-.84527-1.81262L8.70966,9.6839a3.50851,3.50851,0,1,0,.0111,4.63727l5.7132,2.66412a3.49763,3.49763,0,1,0,6.30493-1.526ZM18.00745,5.01056A1.49993,1.49993,0,1,1,16.39551,6.3894,1.49994,1.49994,0,0,1,18.00745,5.01056ZM5.99237,13.49536a1.49989,1.49989,0,1,1,1.61194-1.37878A1.49982,1.49982,0,0,1,5.99237,13.49536Zm11.78211,5.494a1.49993,1.49993,0,1,1,1.61193-1.37885A1.49987,1.49987,0,0,1,17.77448,18.98932Z"></path></svg>';
+    }
+    
+    var oConfig = {              
+         theme: oParams.skin,
+         modules: {
+            syntax: true, 
+            imageResize: {},
+            toolbar: oParams.toolbar,
+            mention: {
+                allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
+                mentionDenotationChars: ["@"],
+                showDenotationChar: false,
+                blotName: 'menthion-link',
+                source: function (searchTerm, renderList, mentionChar) {
+                  $.getJSON(oParams.root_url + 'searchExtended.php?action=get_authors&', { term: searchTerm}, function(data){
+                    renderList(data, searchTerm);
+                  });
+                },
+                renderItem: function(item, searchTerm){
+                  item.id = item.url;
+                  item.value = item.label;
+                  return '@' + item.value;
+                },
+                onSelect: function(item, insertItem){
+                    insertItem(item, false)
+                }
+            },
+        }
+    };
+    
+    if (oParams.toolbar){
+        oConfig.modules.imageUploader = {
+            upload: file => {
+                return new Promise((resolve, reject) => {
+                    const formData = new FormData();
+                    formData.append("file", file);
+                    fetch(oParams.root_url + "storage.php?o=sys_images_editor&t=sys_images_editor&a=upload", {
+                            method: "POST",
+                            body: formData
+                        }
+                    )
+                    .then(response => response.json())
+                    .then(result => {
+                        resolve(result.link);
+                    })
+                    .catch(error => {
+                        reject("Upload failed");
+                    });
+                });
+            }
+        }
+    }
+
+    oEditor = new Quill('#' + oParams.name, oConfig)
+    $(oParams.selector).next().find('button.ql-bold').attr('title', _t('_sys_txt_quill_tooltip_bold'));
+    $(oParams.selector).next().find('button.ql-italic').attr('title', _t('_sys_txt_quill_tooltip_italic'));
+    $(oParams.selector).next().find('button.ql-underline').attr('title', _t('_sys_txt_quill_tooltip_underline'));
+    $(oParams.selector).next().find('button.ql-clean').attr('title', _t('_sys_txt_quill_tooltip_clean'));
+    $(oParams.selector).next().find('button.ql-list[value = "ordered"]').attr('title', _t('_sys_txt_quill_tooltip_list_ordered'));
+    $(oParams.selector).next().find('button.ql-list[value = "bullet"]').attr('title', _t('_sys_txt_quill_tooltip_list_bullet'));
+    $(oParams.selector).next().find('button.ql-indent[value = "-1"]').attr('title', _t('_sys_txt_quill_tooltip_indent_1'));
+    $(oParams.selector).next().find('button.ql-indent[value = "+1"]').attr('title', _t('_sys_txt_quill_tooltip_indent_2'));
+    $(oParams.selector).next().find('button.ql-blockquote').attr('title', _t('_sys_txt_quill_tooltip_blockquote'));
+    $(oParams.selector).next().find('button.ql-direction').attr('title', _t('_sys_txt_quill_tooltip_direction'));
+    $(oParams.selector).next().find('button.ql-script[value="sub"]').attr('title', _t('_sys_txt_quill_tooltip_script_sub'));
+    $(oParams.selector).next().find('button.ql-script[value="super"]').attr('title', _t('_sys_txt_quill_tooltip_script_super'));
+    $(oParams.selector).next().find('button.ql-link').attr('title', _t('_sys_txt_quill_tooltip_link'));
+    $(oParams.selector).next().find('button.ql-image').attr('title', _t('_sys_txt_quill_tooltip_image'));
+    $(oParams.selector).next().find('button.ql-code-block').attr('title', _t('_sys_txt_quill_tooltip_code_block'));
+    $(oParams.selector).next().find('span.ql-color').attr('title', _t('_sys_txt_quill_tooltip_color'));
+    $(oParams.selector).next().find('span.ql-background').attr('title', _t('_sys_txt_quill_tooltip_background'));
+    $(oParams.selector).next().find('span.ql-align').attr('title', _t('_sys_txt_quill_tooltip_align'));
+    $(oParams.selector).next().find('span.ql-header').attr('title', _t('_sys_txt_quill_tooltip_header'));
+     
+    
+    oEditor.keyboard.addBinding({
+        key: ' ',
+        handler: function(range, context) {
+            bx_editor_on_space_enter (oEditor, oParams.selector);
+            return true;
+        }
+    });
+    
+    oEditor.keyboard.bindings[13].unshift({
+        key: 13,
+        handler: (range, context) => {
+            bx_editor_on_space_enter (oEditor, oParams.selector)
+            return true;
+        }
+    });
+    
+    oEditor.on('text-change', function(delta, oldDelta, source) {
+        $(oParams.selector).val(oEditor.container.firstChild.innerHTML);
+    });
+    
+    return oEditor
+}
+    
+function bx_editor_insert_html (sEditorId, sImgId, sHtml) 
+{
+    if ($('#' + sEditorId) &&  $('#' + sEditorId).attr('object_editor')){
+        eval ('oEditor = ' + $('#' + sEditorId).attr('object_editor'));
+        if (oEditor.getSelection())
+            oEditor.clipboard.dangerouslyPasteHTML(oEditor.getSelection().index, sHtml, 'api');
+        else
+             oEditor.clipboard.dangerouslyPasteHTML(0, sHtml, 'api');
+    }
+}
+
+function bx_editor_insert_img (sEditorId, sImgId, sImgUrl, sClasses) {
+
+    if ('undefined' == typeof(sClasses))
+        sClasses = '';
+    
+    bx_editor_insert_html(sEditorId, sImgId, '<img id="' + sImgId + '" class="' + sClasses + '" src="' + sImgUrl + '" />')
+}
+
+function bx_editor_on_space_enter (oEditor, sEditorId)
+{
+    if (typeof glBxEditorOnSpaceEnterTimer !== 'undefined')
+        clearTimeout(glBxEditorOnSpaceEnterTimer);
+    
+    glBxEditorOnSpaceEnterTimer = setTimeout(function () {
+        glBxEditorOnSpaceEnterTimer = undefined;
+        if (typeof glOnSpaceEnterInEditor !== 'undefined' && glOnSpaceEnterInEditor instanceof Array) {
+            for (var i = 0; i < glOnSpaceEnterInEditor.length; i++) {
+                if (typeof glOnSpaceEnterInEditor[i] === "function") {;                                             
+                    glOnSpaceEnterInEditor[i](oEditor.container.firstChild.innerHTML, sEditorId);
+                }
+            }
+        }
+    }, 800);
+}
+
+/** @} */

+ 12 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/inc/version.inc.php

@@ -0,0 +1,12 @@
+<?php defined('BX_DOL') or defined('BX_DOL_INSTALL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaCore UNA Core
+ * @{
+ */
+
+define('BX_DOL_VERSION', '13.0.0-A2'); ///< system files version, for DB version @see bx_get_ver, DB and files version must match
+
+/** @} */

+ 7 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/plugins/autoload.php

@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit55a7ad674772f67174fa967dc73eb510::getLoader();

+ 75 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/plugins/composer/autoload_real.php

@@ -0,0 +1,75 @@
+<?php
+
+// autoload_real.php @generated by Composer
+
+class ComposerAutoloaderInit55a7ad674772f67174fa967dc73eb510
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/ClassLoader.php';
+        }
+    }
+
+    /**
+     * @return \Composer\Autoload\ClassLoader
+     */
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        require __DIR__ . '/platform_check.php';
+
+        spl_autoload_register(array('ComposerAutoloaderInit55a7ad674772f67174fa967dc73eb510', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
+        spl_autoload_unregister(array('ComposerAutoloaderInit55a7ad674772f67174fa967dc73eb510', 'loadClassLoader'));
+
+        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
+        if ($useStaticLoader) {
+            require __DIR__ . '/autoload_static.php';
+
+            call_user_func(\Composer\Autoload\ComposerStaticInit55a7ad674772f67174fa967dc73eb510::getInitializer($loader));
+        } else {
+            $map = require __DIR__ . '/autoload_namespaces.php';
+            foreach ($map as $namespace => $path) {
+                $loader->set($namespace, $path);
+            }
+
+            $map = require __DIR__ . '/autoload_psr4.php';
+            foreach ($map as $namespace => $path) {
+                $loader->setPsr4($namespace, $path);
+            }
+
+            $classMap = require __DIR__ . '/autoload_classmap.php';
+            if ($classMap) {
+                $loader->addClassMap($classMap);
+            }
+        }
+
+        $loader->register(true);
+
+        if ($useStaticLoader) {
+            $includeFiles = Composer\Autoload\ComposerStaticInit55a7ad674772f67174fa967dc73eb510::$files;
+        } else {
+            $includeFiles = require __DIR__ . '/autoload_files.php';
+        }
+        foreach ($includeFiles as $fileIdentifier => $file) {
+            composerRequire55a7ad674772f67174fa967dc73eb510($fileIdentifier, $file);
+        }
+
+        return $loader;
+    }
+}
+
+function composerRequire55a7ad674772f67174fa967dc73eb510($fileIdentifier, $file)
+{
+    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+        require $file;
+
+        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+    }
+}

+ 260 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/plugins/composer/autoload_static.php

@@ -0,0 +1,260 @@
+<?php
+
+// autoload_static.php @generated by Composer
+
+namespace Composer\Autoload;
+
+class ComposerStaticInit55a7ad674772f67174fa967dc73eb510
+{
+    public static $files = array (
+        '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
+        '8dd32984d4cd58147cb41bf3844153c3' => __DIR__ . '/..' . '/chargebee/chargebee-php/lib/ChargeBee.php',
+        '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
+        'c65d09b6820da036953a371c8c73a9b1' => __DIR__ . '/..' . '/facebook/graph-sdk/src/Facebook/polyfills.php',
+    );
+
+    public static $prefixLengthsPsr4 = array (
+        'T' => 
+        array (
+            'Twilio\\' => 7,
+        ),
+        'S' => 
+        array (
+            'Stripe\\' => 7,
+            'Snipe\\BanBuilder\\' => 17,
+            'Sample\\' => 7,
+        ),
+        'P' => 
+        array (
+            'Psr\\Http\\Message\\' => 17,
+            'PayPalHttp\\' => 11,
+            'PayPalCheckoutSdk\\' => 18,
+            'PHPMailer\\PHPMailer\\' => 20,
+        ),
+        'M' => 
+        array (
+            'MatthiasMullie\\PathConverter\\' => 29,
+            'MatthiasMullie\\Minify\\' => 22,
+        ),
+        'I' => 
+        array (
+            'Intervention\\Image\\' => 19,
+        ),
+        'G' => 
+        array (
+            'GuzzleHttp\\Psr7\\' => 16,
+        ),
+        'F' => 
+        array (
+            'Facebook\\' => 9,
+        ),
+        'E' => 
+        array (
+            'Embera\\' => 7,
+        ),
+        'A' => 
+        array (
+            'AvtoDev\\Composer\\Cleanup\\' => 25,
+            'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => 38,
+        ),
+    );
+
+    public static $prefixDirsPsr4 = array (
+        'Twilio\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/twilio/sdk/src/Twilio',
+        ),
+        'Stripe\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/stripe/stripe-php/lib',
+        ),
+        'Snipe\\BanBuilder\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/snipe/banbuilder/src',
+        ),
+        'Sample\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/paypal/paypal-checkout-sdk/samples',
+        ),
+        'Psr\\Http\\Message\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/psr/http-message/src',
+            1 => __DIR__ . '/..' . '/psr/http-factory/src',
+        ),
+        'PayPalHttp\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/paypal/paypalhttp/lib/PayPalHttp',
+        ),
+        'PayPalCheckoutSdk\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/paypal/paypal-checkout-sdk/lib/PayPalCheckoutSdk',
+        ),
+        'PHPMailer\\PHPMailer\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
+        ),
+        'MatthiasMullie\\PathConverter\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/matthiasmullie/path-converter/src',
+        ),
+        'MatthiasMullie\\Minify\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/matthiasmullie/minify/src',
+        ),
+        'Intervention\\Image\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/intervention/image/src/Intervention/Image',
+        ),
+        'GuzzleHttp\\Psr7\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
+        ),
+        'Facebook\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/facebook/graph-sdk/src/Facebook',
+        ),
+        'Embera\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/mpratt/embera/src/Embera',
+        ),
+        'AvtoDev\\Composer\\Cleanup\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/avto-dev/composer-cleanup-plugin/src',
+        ),
+        'Akeeba\\Engine\\Postproc\\Connector\\S3v4\\' => 
+        array (
+            0 => __DIR__ . '/..' . '/akeeba/s3/src',
+        ),
+    );
+
+    public static $prefixesPsr0 = array (
+        'P' => 
+        array (
+            'Parsedown' => 
+            array (
+                0 => __DIR__ . '/..' . '/erusev/parsedown',
+            ),
+        ),
+        'O' => 
+        array (
+            'OAuth\\Unit' => 
+            array (
+                0 => __DIR__ . '/..' . '/lusitanian/oauth/tests',
+            ),
+            'OAuth2' => 
+            array (
+                0 => __DIR__ . '/..' . '/bshaffer/oauth2-server-php/src',
+            ),
+            'OAuth' => 
+            array (
+                0 => __DIR__ . '/..' . '/lusitanian/oauth/src',
+            ),
+        ),
+        'L' => 
+        array (
+            'Less' => 
+            array (
+                0 => __DIR__ . '/..' . '/wikimedia/less.php/lib',
+            ),
+        ),
+        'H' => 
+        array (
+            'HTMLPurifier' => 
+            array (
+                0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
+            ),
+        ),
+    );
+
+    public static $classMap = array (
+        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+        'Recurly_Account' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/account.php',
+        'Recurly_AccountAcquisition' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/account_acquisition.php',
+        'Recurly_AccountBalance' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/account_balance.php',
+        'Recurly_AccountList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/account_list.php',
+        'Recurly_Addon' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/addon.php',
+        'Recurly_AddonList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/addon_list.php',
+        'Recurly_Address' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/address.php',
+        'Recurly_Adjustment' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/adjustment.php',
+        'Recurly_AdjustmentList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/adjustment_list.php',
+        'Recurly_ApiRateLimitError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_Base' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/base.php',
+        'Recurly_BillingInfo' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/billing_info.php',
+        'Recurly_Client' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/client.php',
+        'Recurly_ClientResponse' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/response.php',
+        'Recurly_ConfigurationError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_ConnectionError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_Coupon' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/coupon.php',
+        'Recurly_CouponList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/coupon_list.php',
+        'Recurly_CouponRedemption' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/redemption.php',
+        'Recurly_CouponRedemptionList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/redemption_list.php',
+        'Recurly_CreditPayment' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/credit_payment.php',
+        'Recurly_CreditPaymentList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/credit_payment_list.php',
+        'Recurly_Currency' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/currency.php',
+        'Recurly_CurrencyList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/currency_list.php',
+        'Recurly_CustomField' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/custom_field.php',
+        'Recurly_CustomFieldList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/custom_field_list.php',
+        'Recurly_Delivery' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/delivery.php',
+        'Recurly_Error' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_ErrorList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/error_list.php',
+        'Recurly_ExportDate' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/export_date.php',
+        'Recurly_ExportDateList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/export_date_list.php',
+        'Recurly_ExportFile' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/export_file.php',
+        'Recurly_ExportFileList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/export_file_list.php',
+        'Recurly_FieldError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_ForgedQueryStringError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_FraudInfo' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/fraud_info.php',
+        'Recurly_GiftCard' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/gift_card.php',
+        'Recurly_GiftCardList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/gift_card_list.php',
+        'Recurly_HmacHash' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/util/hmac_hash.php',
+        'Recurly_Invoice' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/invoice.php',
+        'Recurly_InvoiceCollection' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/invoice_collection.php',
+        'Recurly_InvoiceList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/invoice_list.php',
+        'Recurly_Link' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/link.php',
+        'Recurly_MeasuredUnit' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/measured_unit.php',
+        'Recurly_MeasuredUnitList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/measured_unit_list.php',
+        'Recurly_NotFoundError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_Note' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/note.php',
+        'Recurly_NoteList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/note_list.php',
+        'Recurly_Object' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/base.php',
+        'Recurly_Pager' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/pager.php',
+        'Recurly_Plan' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/plan.php',
+        'Recurly_PlanList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/plan_list.php',
+        'Recurly_Purchase' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/purchase.php',
+        'Recurly_PushNotification' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/push_notification.php',
+        'Recurly_RequestError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_Resource' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/resource.php',
+        'Recurly_ServerError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_ShippingAddress' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/shipping_address.php',
+        'Recurly_ShippingAddressList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/shipping_address_list.php',
+        'Recurly_Stub' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/stub.php',
+        'Recurly_Subscription' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/subscription.php',
+        'Recurly_SubscriptionAddOn' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/subscription_addon.php',
+        'Recurly_SubscriptionList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/subscription_list.php',
+        'Recurly_Tax_Detail' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/tax_detail.php',
+        'Recurly_Transaction' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/transaction.php',
+        'Recurly_TransactionError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/transaction_error.php',
+        'Recurly_TransactionList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/transaction_list.php',
+        'Recurly_UnauthorizedError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_UniqueCouponCodeList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/unique_coupon_code_list.php',
+        'Recurly_Usage' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/usage.php',
+        'Recurly_UsageList' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/usage_list.php',
+        'Recurly_ValidationError' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/errors.php',
+        'Recurly_js' => __DIR__ . '/..' . '/recurly/recurly-client/lib/recurly/recurly_js.php',
+        'S3v4\\S3' => __DIR__ . '/..' . '/tpyo/amazon-s3-php-class/S3.php',
+        'S3v4\\S3Exception' => __DIR__ . '/..' . '/tpyo/amazon-s3-php-class/S3.php',
+        'S3v4\\S3Request' => __DIR__ . '/..' . '/tpyo/amazon-s3-php-class/S3.php',
+        'lessc' => __DIR__ . '/..' . '/wikimedia/less.php/lessc.inc.php',
+    );
+
+    public static function getInitializer(ClassLoader $loader)
+    {
+        return \Closure::bind(function () use ($loader) {
+            $loader->prefixLengthsPsr4 = ComposerStaticInit55a7ad674772f67174fa967dc73eb510::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit55a7ad674772f67174fa967dc73eb510::$prefixDirsPsr4;
+            $loader->prefixesPsr0 = ComposerStaticInit55a7ad674772f67174fa967dc73eb510::$prefixesPsr0;
+            $loader->classMap = ComposerStaticInit55a7ad674772f67174fa967dc73eb510::$classMap;
+
+        }, null, ClassLoader::class);
+    }
+}

+ 304 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/plugins/composer/installed.php

@@ -0,0 +1,304 @@
+<?php return array(
+    'root' => array(
+        'pretty_version' => 'dev-master',
+        'version' => 'dev-master',
+        'type' => 'library',
+        'install_path' => __DIR__ . '/../../',
+        'aliases' => array(),
+        'reference' => '4adee2ed0f027893b7b52518958b0d966790211b',
+        'name' => 'unaio/una',
+        'dev' => true,
+    ),
+    'versions' => array(
+        'achingbrain/php5-akismet' => array(
+            'pretty_version' => '0.5',
+            'version' => '0.5.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../achingbrain/php5-akismet',
+            'aliases' => array(),
+            'reference' => 'master',
+            'dev_requirement' => false,
+        ),
+        'akeeba/s3' => array(
+            'pretty_version' => 'dev-main',
+            'version' => 'dev-main',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../akeeba/s3',
+            'aliases' => array(),
+            'reference' => '96208915514b19e7789ea053c6a109b212864001',
+            'dev_requirement' => false,
+        ),
+        'avto-dev/composer-cleanup-plugin' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'type' => 'composer-plugin',
+            'install_path' => __DIR__ . '/../avto-dev/composer-cleanup-plugin',
+            'aliases' => array(
+                0 => '9999999-dev',
+            ),
+            'reference' => '75187ca4854265174021765e3b67cb973dc37723',
+            'dev_requirement' => false,
+        ),
+        'bshaffer/oauth2-server-php' => array(
+            'pretty_version' => 'v1.11.1',
+            'version' => '1.11.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../bshaffer/oauth2-server-php',
+            'aliases' => array(),
+            'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
+            'dev_requirement' => false,
+        ),
+        'chargebee/chargebee-php' => array(
+            'pretty_version' => 'v2.8.3',
+            'version' => '2.8.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../chargebee/chargebee-php',
+            'aliases' => array(),
+            'reference' => 'e0819230cd7a8364337a0a228f7aecab80b6776b',
+            'dev_requirement' => false,
+        ),
+        'curl/cacert' => array(
+            'pretty_version' => '0.0.1',
+            'version' => '0.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../curl/cacert',
+            'aliases' => array(),
+            'reference' => NULL,
+            'dev_requirement' => false,
+        ),
+        'erusev/parsedown' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../erusev/parsedown',
+            'aliases' => array(
+                0 => '9999999-dev',
+            ),
+            'reference' => '6598f3860c2698fe2f0f1bc98212fc01d0a1893c',
+            'dev_requirement' => false,
+        ),
+        'ezyang/htmlpurifier' => array(
+            'pretty_version' => 'v4.13.0',
+            'version' => '4.13.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ezyang/htmlpurifier',
+            'aliases' => array(),
+            'reference' => '08e27c97e4c6ed02f37c5b2b20488046c8d90d75',
+            'dev_requirement' => false,
+        ),
+        'facebook/graph-sdk' => array(
+            'pretty_version' => '5.7.0',
+            'version' => '5.7.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../facebook/graph-sdk',
+            'aliases' => array(),
+            'reference' => '2d8250638b33d73e7a87add65f47fabf91f8ad9b',
+            'dev_requirement' => false,
+        ),
+        'ffmpeg/ffmpeg' => array(
+            'pretty_version' => '4.4.0',
+            'version' => '4.4.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ffmpeg/ffmpeg',
+            'aliases' => array(),
+            'reference' => NULL,
+            'dev_requirement' => false,
+        ),
+        'guzzlehttp/psr7' => array(
+            'pretty_version' => '2.1.0',
+            'version' => '2.1.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../guzzlehttp/psr7',
+            'aliases' => array(),
+            'reference' => '089edd38f5b8abba6cb01567c2a8aaa47cec4c72',
+            'dev_requirement' => false,
+        ),
+        'intervention/image' => array(
+            'pretty_version' => '2.7.0',
+            'version' => '2.7.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../intervention/image',
+            'aliases' => array(),
+            'reference' => '9a8cc99d30415ec0b3f7649e1647d03a55698545',
+            'dev_requirement' => false,
+        ),
+        'lusitanian/oauth' => array(
+            'pretty_version' => 'v0.8.11',
+            'version' => '0.8.11.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../lusitanian/oauth',
+            'aliases' => array(),
+            'reference' => 'fc11a53db4b66da555a6a11fce294f574a8374f9',
+            'dev_requirement' => false,
+        ),
+        'matthiasmullie/minify' => array(
+            'pretty_version' => '1.3.66',
+            'version' => '1.3.66.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../matthiasmullie/minify',
+            'aliases' => array(),
+            'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
+            'dev_requirement' => false,
+        ),
+        'matthiasmullie/path-converter' => array(
+            'pretty_version' => '1.1.3',
+            'version' => '1.1.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../matthiasmullie/path-converter',
+            'aliases' => array(),
+            'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
+            'dev_requirement' => false,
+        ),
+        'mpratt/embera' => array(
+            'pretty_version' => '2.0.22',
+            'version' => '2.0.22.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../mpratt/embera',
+            'aliases' => array(),
+            'reference' => '79a5b789a674b4fcab374e5669c0270b910f28a9',
+            'dev_requirement' => false,
+        ),
+        'paypal/paypal-checkout-sdk' => array(
+            'pretty_version' => '1.0.2',
+            'version' => '1.0.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../paypal/paypal-checkout-sdk',
+            'aliases' => array(),
+            'reference' => '19992ce7051ff9e47e643f28abb8cc1b3e5f1812',
+            'dev_requirement' => false,
+        ),
+        'paypal/paypalhttp' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../paypal/paypalhttp',
+            'aliases' => array(),
+            'reference' => '7b09c89c80828e842c79230e7f156b61fbb68d25',
+            'dev_requirement' => false,
+        ),
+        'phpmailer/phpmailer' => array(
+            'pretty_version' => 'v6.5.1',
+            'version' => '6.5.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpmailer/phpmailer',
+            'aliases' => array(),
+            'reference' => 'dd803df5ad7492e1b40637f7ebd258fee5ca7355',
+            'dev_requirement' => false,
+        ),
+        'psr/http-factory' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-factory',
+            'aliases' => array(),
+            'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
+            'dev_requirement' => false,
+        ),
+        'psr/http-factory-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'psr/http-message' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/http-message',
+            'aliases' => array(),
+            'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
+            'dev_requirement' => false,
+        ),
+        'psr/http-message-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '1.0',
+            ),
+        ),
+        'ralouphie/getallheaders' => array(
+            'pretty_version' => '3.0.3',
+            'version' => '3.0.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ralouphie/getallheaders',
+            'aliases' => array(),
+            'reference' => '120b605dfeb996808c31b6477290a714d356e822',
+            'dev_requirement' => false,
+        ),
+        'recurly/recurly-client' => array(
+            'pretty_version' => '2.10.7',
+            'version' => '2.10.7.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../recurly/recurly-client',
+            'aliases' => array(),
+            'reference' => 'f60e9247b56617c9d5a9c6368b701a17b957992b',
+            'dev_requirement' => false,
+        ),
+        'snipe/banbuilder' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../snipe/banbuilder',
+            'aliases' => array(
+                0 => '9999999-dev',
+            ),
+            'reference' => '621d6d857400983d0fd6cd291f105a835a317748',
+            'dev_requirement' => false,
+        ),
+        'stripe/stripe-php' => array(
+            'pretty_version' => 'v7.100.0',
+            'version' => '7.100.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../stripe/stripe-php',
+            'aliases' => array(),
+            'reference' => '3dfc3dcd5d967a14d2852f34e544188af5f9b799',
+            'dev_requirement' => false,
+        ),
+        'tpyo/amazon-s3-php-class' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../tpyo/amazon-s3-php-class',
+            'aliases' => array(
+                0 => '9999999-dev',
+            ),
+            'reference' => '3f720a0144843c214b9444e626119dbe12ecc180',
+            'dev_requirement' => false,
+        ),
+        'twilio/sdk' => array(
+            'pretty_version' => '5.42.2',
+            'version' => '5.42.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../twilio/sdk',
+            'aliases' => array(),
+            'reference' => '0cfcb871b18a9c427dd9e8f0ed7458d43009b48a',
+            'dev_requirement' => false,
+        ),
+        'unaio/amazon-s3-php-class-hmac-v2' => array(
+            'pretty_version' => '0.5',
+            'version' => '0.5.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../unaio/amazon-s3-php-class-hmac-v2',
+            'aliases' => array(),
+            'reference' => 'main',
+            'dev_requirement' => false,
+        ),
+        'unaio/una' => array(
+            'pretty_version' => 'dev-master',
+            'version' => 'dev-master',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../../',
+            'aliases' => array(),
+            'reference' => '4adee2ed0f027893b7b52518958b0d966790211b',
+            'dev_requirement' => false,
+        ),
+        'wikimedia/less.php' => array(
+            'pretty_version' => 'v3.1.0',
+            'version' => '3.1.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../wikimedia/less.php',
+            'aliases' => array(),
+            'reference' => 'a486d78b9bd16b72f237fc6093aa56d69ce8bd13',
+            'dev_requirement' => false,
+        ),
+    ),
+);

+ 1446 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/template/scripts/BxBaseCmts.php

@@ -0,0 +1,1446 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaBaseView UNA Base Representation Classes
+ * @{
+ */
+
+/**
+ * @see BxDolCmts
+ */
+class BxBaseCmts extends BxDolCmts
+{
+    protected static $_sTmplContentElementBlock;
+    protected static $_sTmplContentElementInline;
+    protected static $_sTmplContentDoCommentLabel;
+    protected static $_sTmplContentCounter;
+
+    protected $_sTmplNameItem;
+    protected $_sTmplNameItemContent;
+
+    protected $_sJsObjClass;
+    protected $_sJsObjName;
+    protected $_sStylePrefix;
+
+    protected $_aHtmlIds;
+
+    protected $_aElementDefaults;
+    
+    protected $_aAclId2Name;
+
+    function __construct( $sSystem, $iId, $iInit = true, $oTemplate = false)
+    {
+        parent::__construct($sSystem, $iId, $iInit, $oTemplate);
+        if (empty($sSystem))
+            return;
+
+        $this->_sTmplNameItem = 'comment.html';
+        $this->_sTmplNameItemContent = 'comment_content.html';
+
+        $this->_sJsObjClass = 'BxDolCmts';
+        $this->_sJsObjName = 'oCmts' . bx_gen_method_name($sSystem, array('_' , '-')) . '_' .str_replace('-', 'n', $iId);
+        $this->_sStylePrefix = isset($this->_aSystem['root_style_prefix']) ? $this->_aSystem['root_style_prefix'] : 'cmt';
+
+        $sHtmlId = str_replace(array('_' , ' '), array('-', '-'), $sSystem) . '-' . $iId;
+
+        $this->_aHtmlIds = array(
+            'main' => 'bx-cmt-' . $sHtmlId,
+            'counter' => 'bx-cmt-counter-' . $sHtmlId
+        );
+
+        $this->_aElementDefaults = array(
+            'show_do_comment_as_button' => false,
+            'show_do_comment_as_button_small' => false,
+            'show_do_comment_image' => false,
+            'show_do_comment_icon' => true,
+            'show_do_comment_label' => false,
+            'show_counter' => true,
+            'show_counter_empty' => false
+        );
+
+        $this->_aAclId2Name = array();
+        $aAclLevels = BxDolAcl::getInstance()->getMemberships(false, false, false);
+        foreach($aAclLevels as $iAclId => $sAclName)
+            $this->_aAclId2Name[$iAclId] = str_replace('_', '-', str_replace('_adm_prm_txt_level_', '', $sAclName));
+
+        if(empty(self::$_sTmplContentElementBlock))
+            self::$_sTmplContentElementBlock = $this->_oTemplate->getHtml('comment_element_block.html');
+
+        if(empty(self::$_sTmplContentElementInline))
+            self::$_sTmplContentElementInline = $this->_oTemplate->getHtml('comment_element_inline.html');
+
+        if(empty(self::$_sTmplContentDoCommentLabel))
+            self::$_sTmplContentDoCommentLabel = $this->_oTemplate->getHtml('comment_do_comment_label.html');
+
+        if(empty(self::$_sTmplContentCounter))
+            self::$_sTmplContentCounter = $this->_oTemplate->getHtml('comment_counter.html');
+
+        $this->_oTemplate->addJsTranslation('_sys_txt_cmt_loading');
+    }
+
+    /**
+     * Add comments CSS/JS
+     */
+    public function addCssJs ()
+    {
+        $oForm = BxDolForm::getObjectInstance($this->_sFormObject, $this->_sFormDisplayPost);
+        $oForm->addCssJs();
+    }
+
+    public function getJsObjectName()
+    {
+        return $this->_sJsObjName;
+    }
+
+    /**
+     * Get initialization section of comments box
+     *
+     * @return string
+     */
+    public function getJsScript($aBp = array(), $aDp = array())
+    {
+        $bMinPostForm = isset($aDp['min_post_form']) ? $aDp['min_post_form'] : $this->_bMinPostForm;
+
+        $aParams = array(
+            'sObjName' => $this->_sJsObjName,
+            'sRootUrl' => BX_DOL_URL_ROOT,
+            'sSystem' => $this->getSystemName(),
+            'iAuthorId' => $this->_getAuthorId(),
+            'iObjId' => $this->getId(),
+            'sBaseUrl' => $this->getBaseUrl(),
+            'sPostFormPosition' => $this->_aSystem['post_form_position'],
+            'sBrowseType' => $this->_sBrowseType,
+            'sDisplayType' => $this->_sDisplayType,
+            'iDisplayStructure' => isset($aDp['structure']) && !empty($aDp['structure']) ? 1 : 0,
+            'iMinPostForm' => $bMinPostForm ? 1 : 0,
+            'sStylePrefix' => $this->_sStylePrefix,
+        );
+
+        $this->addCssJs();
+        return $this->_oTemplate->_wrapInTagJsCode("if(window['" . $this->_sJsObjName . "'] == undefined) var " . $this->_sJsObjName . " = new " . $this->_sJsObjClass . "(" . json_encode($aParams) . "); " . $this->_sJsObjName . ".cmtInit();");
+    }
+
+    /**
+     * get full comments block with initializations
+     */
+    function getCommentsBlock($aBp = array(), $aDp = array())
+    {
+        $mixedResult = $this->isViewAllowed();
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return $mixedResult;
+        
+        $this->_getParams($aBp, $aDp);
+
+        //add live update
+        $this->actionResumeLiveUpdate();
+
+        $sServiceCall = BxDolService::getSerializedService('system', 'get_live_update', array($this->_sSystem, $this->_iId, $this->_getAuthorId(), '{count}'), 'TemplCmtsServices');
+        BxDolLiveUpdates::getInstance()->add($this->_sSystem . '_live_updates_cmts_' . $this->_iId, 1, $sServiceCall);
+        //add live update
+
+        $sComments = $this->getComments($aBp, $aDp);
+        $sCommentsPinned = $this->getCommentsPinned($aBp, $aDp);
+        $sContentBefore = $this->_getContentBefore($aBp, $aDp);
+        $sContentAfter = $this->_getContentAfter($aBp, $aDp);
+        $sPostFormTop = $this->getFormBoxPost($aBp, array_merge($aDp, array('type' => $this->_sDisplayType, 'position' => BX_CMT_PFP_TOP)));
+        $sPostFormBottom = $this->getFormBoxPost($aBp, array_merge($aDp, array('type' => $this->_sDisplayType, 'position' => BX_CMT_PFP_BOTTOM)));
+        $sJsContent = $this->getJsScript($aBp, $aDp);
+
+        $sBlockTitle = _t($this->_aT['block_comments_title'], $this->getCommentsCountAll());
+        $sBlockMenu = $this->_getControlsBox();
+
+        bx_alert('system', 'view_comments', 0, 0, array(
+            'object' => $this,
+            'system' => $this->_sSystem,
+            'id' => $this->getId(),
+            'params_browse' => $aBp,
+            'params_display' => $aDp,
+            'post_form_top' => &$sPostFormTop,
+            'content_before' => &$sContentBefore,
+            'comments' => &$sComments,
+            'comments_pinned' => &$sCommentsPinned,
+            'content_after' => &$sContentAfter,
+            'post_form_bottom'  => &$sPostFormBottom,
+            'js_content' => &$sJsContent,
+            'block_title' => &$sBlockTitle,
+            'block_menu' => &$sBlockMenu,
+        ));
+
+        $sContent = $this->_oTemplate->parseHtmlByName('comments_block.html', array(
+            'system' => $this->_sSystem,
+            'list_anchor' => $this->getListAnchor(),
+            'id' => $this->getId(),
+            'content_before' => $sContentBefore,
+            'comments' => $sComments,
+            'comments_pinned' => $sCommentsPinned,
+            'bx_if:show_divider_hidden' => array(
+                'condition' => empty($sCommentsPinned),
+                'content' => array()
+            ),
+            'content_after' => $sContentAfter,
+            'post_form_top' => $sPostFormTop,
+            'post_form_bottom'  => $sPostFormBottom,
+            'view_image_popup' => $this->_getViewImagePopup(),
+            'script' => $sJsContent
+        ));
+
+        return $aDp['in_designbox'] ? DesignBoxContent($sBlockTitle, $sContent, BX_DB_DEF, $sBlockMenu) : array(
+            'title' => $sBlockTitle,
+            'content' => $sContent,
+            'menu' => $sBlockMenu,
+        );
+    }
+
+    /**
+     * get comments list for specified parent comment
+     *
+     * @param array $aBp - browse params array
+     * @param array $aDp - display params array
+     *
+     */
+    function getComments($aBp = array(), $aDp = array())
+    {
+        $this->_prepareParams($aBp, $aDp);
+
+        $aCmts = $this->getCommentsArray($aBp['vparent_id'], $aBp['filter'], $aBp['order'], $aBp['start'], $aBp['per_view']);
+        if(empty($aCmts) || !is_array($aCmts)) {
+            if((int)$aBp['parent_id'] == 0 && !isLogged()) {
+                $oPermalink = BxDolPermalinks::getInstance();
+                return MsgBox(_t('_cmt_msg_login_required', $oPermalink->permalink('page.php?i=login'), $oPermalink->permalink('page.php?i=create-account')));
+            }
+
+            return isset($aDp['show_empty']) && $aDp['show_empty'] === true ? $this->_getEmpty($aDp) : '';
+        }
+
+        $sCmts = '';
+        foreach($aCmts as $k => $aCmt)
+            $sCmts .= $this->getComment($aCmt, $aBp, $aDp);
+        $sCmts = $this->_getMoreLink($sCmts, $aBp, $aDp);       
+
+        return $sCmts;
+    }
+
+    function getCommentsPinned($aBp = array(), $aDp = array())
+    {
+        $this->_prepareParams($aBp, $aDp);
+
+        $aCmts = $this->getCommentsArray($aBp['vparent_id'], BX_CMT_FILTER_PINNED, $aBp['order'], 0, -1);
+        if(empty($aCmts) || !is_array($aCmts))
+            return '';
+
+        $sCmts = '';
+        foreach($aCmts as $k => $aCmt)
+            $sCmts .= $this->getComment($aCmt, $aBp, $aDp);
+
+        return $sCmts;
+    }
+
+    public function getCommentsByStructure($aBp = array(), $aDp = array())
+    {
+        if(empty($aDp['structure']))
+            return isset($aDp['show_empty']) && $aDp['show_empty'] === true ? $this->_getEmpty($aDp) : '';
+
+        $aBp['count'] = count($aDp['structure']);
+        $this->_prepareParams($aBp, $aDp);
+        $aDp['structure'] = array_slice($aDp['structure'], $aBp['start'], $aBp['per_view'], true);
+
+        $sCmts = '';
+        foreach($aDp['structure'] as $iCmtId => $aCmt)
+            $sCmts .= $this->getComment($iCmtId, $aBp, $aDp);
+
+        $sCmts = $this->_getMoreLink($sCmts, $aBp, $aDp);
+        return $sCmts;
+    }    
+
+    /**
+     * get comment view block with initializations
+     */
+    function getCommentBlock($iCmtId = 0, $aBp = array(), $aDp = array())
+    {
+        $mixedResult = $this->isViewAllowed();
+        if($mixedResult !== CHECK_ACTION_RESULT_ALLOWED)
+            return $mixedResult;
+
+        $aBp = array_merge(array('type' => $this->_sBrowseType), $aBp);
+        $aDp = array_merge(array('type' => BX_CMT_DISPLAY_THREADED), $aDp);
+
+        //--- Beg: Using pregenerated structure
+        $mixedStructure = $this->getCommentStructure((int)$iCmtId, $aBp, $aDp);
+        if($mixedStructure !== false)
+            $aDp['structure'] = $mixedStructure;
+        //--- End: Using pregenerated structure
+
+        $sComment = $this->getComment($iCmtId, $aBp, $aDp);
+        if (!$sComment)
+            return '';
+
+        return $this->_oTemplate->parseHtmlByName('comment_block.html', array(
+            'system' => $this->_sSystem,
+            'id' => $this->getId(),
+            'comment' => $sComment,
+            'view_image_popup' => $this->_getViewImagePopup(), 
+            'script' => $this->getJsScript($aBp, $aDp)
+        ));
+    }
+    
+    /**
+     * get one just posted comment
+     *
+     * @param  int    $iCmtId - comment id
+     * @return string
+     */
+    function getComment($mixedCmt, $aBp = array(), $aDp = array())
+    {
+        $iUserId = $this->_getAuthorId();
+        $aCmt = !is_array($mixedCmt) ? $this->getCommentRow((int)$mixedCmt) : $mixedCmt;
+        if (!$aCmt)
+            return '';
+
+        list($sAuthorName, $sAuthorLink, $sAuthorIcon) = $this->_getAuthorInfo($aCmt['cmt_author_id']);
+
+        $sClass = $sClassCnt = '';
+        if(isset($aCmt['vote_rate']) && (float)$aCmt['vote_rate'] < $this->_aSystem['viewing_threshold']) {
+            $this->_oTemplate->pareseHtmlByName('comment_hidden.html', array(
+                'js_object' => $this->_sJsObjName,
+                'id' => $aCmt['cmt_id'],
+                'title' => bx_process_output(_t('_hidden_comment', $sAuthorName)),
+                'bx_if:show_replies' => array(
+                    'condition' => $aCmt['cmt_replies'] > 0,
+                    'content' => array(
+                        'replies' => _t('_Show N replies', $aCmt['cmt_replies'])
+                    )
+                )
+            ));
+
+            $sClass = ' ' . $this->_sStylePrefix . '-hidden';
+        }
+
+        if($aCmt['cmt_author_id'] == $iUserId)
+            $sClass .= ' ' . $this->_sStylePrefix . '-mine';
+
+        $aAuthorAcl = BxDolAcl::getInstance()->getMemberMembershipInfo($aCmt['cmt_author_id']);
+        if(!empty($aAuthorAcl) && isset($this->_aAclId2Name[$aAuthorAcl['id']]))
+            $sClass .= ' ' . $this->_sStylePrefix . '-aml-' . $this->_aAclId2Name[$aAuthorAcl['id']];
+
+        if(!empty($aDp['blink']) && in_array($aCmt['cmt_id'], $aDp['blink']))
+            $sClass .= ' ' . $this->_sStylePrefix . '-blink';
+
+        if(!empty($aDp['class_comment']))
+            $sClass .= ' ' . $aDp['class_comment'];
+
+        if(!empty($aDp['class_comment_content']))
+            $sClassCnt .= ' ' . $aDp['class_comment_content'];
+
+        $sActions = $this->_getActionsBox($aCmt, $aDp);
+
+        $aTmplReplyTo = array();
+        if((int)$aCmt['cmt_parent_id'] != 0) {
+            $aParent = $this->getCommentRow($aCmt['cmt_parent_id']);
+
+            if(!empty($aParent) && is_array($aParent)) {
+                $oProfile = $this->_getAuthorObject($aParent['cmt_author_id']);
+                $sParAuthorName = $oProfile->getDisplayName();
+                $sParAuthorUnit = $oProfile->getUnit(0, array('template' => array('name' => 'unit_wo_info_links', 'size' => 'icon')));
+
+                $aTmplReplyTo = array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'par_cmt_link' => $this->getItemUrl($aCmt['cmt_parent_id']),
+                    'par_cmt_title' => bx_html_attribute(_t('_in_reply_to_x', $sParAuthorName)),
+                    'par_cmt_author' => $sParAuthorName,
+                    'par_cmt_author_unit' => $sParAuthorUnit
+                );
+            }
+        }
+
+        $sReplies = '';
+        if(!empty($aDp)) {
+            $aDp['show_empty'] = false;
+
+            if(!empty($aDp['structure'][$aCmt['cmt_id']]) && is_array($aDp['structure'][$aCmt['cmt_id']])) {
+                if(!empty($aDp['structure'][$aCmt['cmt_id']]['items'])) {
+                    $aDp['structure'] = $aDp['structure'][$aCmt['cmt_id']]['items'];
+                    $sReplies = $this->getCommentsByStructure(array('parent_id' => $aCmt['cmt_id'], 'type' => $aBp['type']), $aDp);
+                }
+            } 
+            else if((int)$aCmt['cmt_replies'] > 0 && $aDp['type'] == BX_CMT_DISPLAY_THREADED)
+                $sReplies = $this->getComments(array('parent_id' => $aCmt['cmt_id'], 'vparent_id' => $aCmt['cmt_id'], 'type' => $aBp['type']), $aDp);
+        }
+
+        $aTmplVarsMeta = array();
+        if(!empty($this->_sMenuObjMeta)) {
+            $oMenuMeta = BxDolMenu::getObjectInstance($this->_sMenuObjMeta, $this->_oTemplate);
+            if($oMenuMeta) {
+                $oMenuMeta->setCmtsData($this, $aCmt['cmt_id']);
+
+                $aTmplVarsMeta = array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'meta' => $oMenuMeta->getCode()
+                );
+            }
+        }
+
+        $sContent = $this->_getContent($aCmt);
+
+        $sResult = $this->_oTemplate->parseHtmlByName($this->_sTmplNameItem, array_merge(array(
+            'system' => $this->_sSystem,
+            'style_prefix' => $this->_sStylePrefix,
+            'js_object' => $this->_sJsObjName,
+            'id' => $aCmt['cmt_id'],
+            'anchor' => $this->getItemAnchor($aCmt['cmt_id']),
+            'class' => $sClass,
+            'class_cnt' => $sClassCnt,
+            'bx_if:show_reply_to' => array(
+                'condition' => !empty($aTmplReplyTo),
+                'content' => $aTmplReplyTo
+            ),
+            'bx_if:meta' => array(
+                'condition' => !empty($aTmplVarsMeta),
+                'content' => $aTmplVarsMeta
+            ),
+            'bx_if:show_pinned' => array(
+                'condition' => (int)$aCmt['cmt_pinned'] > 0,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                )
+            ),
+            'content' => $sContent,
+            'actions' => $sActions,
+            'replies' =>  $sReplies,
+        ), $this->_getTmplVarsAuthor($aCmt)));
+        
+        bx_alert('system', 'view_comment', $aCmt['cmt_id'], 0, array('comment' => $aCmt, 'system' => $this->_sSystem, 'override_result' => &$sResult));
+        
+        return $sResult;
+    }
+
+    public function getCommentStructure($iCmtId, $aBp = array(), $aDp = array())
+    {
+        $aRoot = $this->getCommentRow((int)$iCmtId);
+
+        $aBps = $aBp;
+        if(!empty($aRoot))
+            $aBps['parent_id'] = $aRoot['cmt_id'];
+        $this->_prepareStructureBp($aDp['type'], $aBps);
+
+        $iLevel = 0;
+        $aStructure = array();
+        $this->_getStructure($aRoot, $aBps, $iLevel, $aStructure);
+
+        return !empty($aStructure) && is_array($aStructure) ? $aStructure : false;
+    }
+
+    function getCommentSearch($iCmtId, &$sAddon)
+    {
+        $aBp = array();
+        $aDp = array(
+            'type' => BX_CMT_DISPLAY_FLAT, 
+            'view_only' => true
+        );
+
+        if(empty($sAddon))
+            $sAddon = $this->getJsScript($aBp, $aDp);
+
+        return $this->_oTemplate->parseHtmlByName('comment_search.html', array(
+            'comment' => $this->getComment($iCmtId, $aBp, $aDp),
+            'view_image_popup' => $this->_getViewImagePopup(), 
+        )); 
+    }
+
+    /**
+     * get one comment for "Live Search"
+     *
+     * @param  int    $iCmtId - comment id
+     * @return string
+     */
+    function getCommentLiveSearch($mixedCmt, $aParams = array())
+    {
+        $aCmt = !is_array($mixedCmt) ? $this->getCommentRow((int)$mixedCmt) : $mixedCmt;
+
+        list($sAuthorName, $sAuthorLink, $sAuthorIcon) = $this->_getAuthorInfo($aCmt['cmt_author_id']);
+        $bAuthorIcon = !empty($sAuthorIcon);
+
+        $sViewLink = $this->getViewUrl($aCmt['cmt_id']);
+        if(empty($sViewLink))
+            $sViewLink = '#';
+
+        return $this->_oTemplate->parseHtmlByName('comment_live_search.html', array(
+            'bx_if:show_icon' => array(
+                'condition' => $bAuthorIcon,
+                'content' => array(
+                    'author_icon' => $sAuthorIcon,
+        			'view_link' => $sViewLink
+                )
+            ),
+            'bx_if:show_icon_empty' => array(
+                'condition' => !$bAuthorIcon,
+                'content' => array()
+            ),
+            'view_link' => $sViewLink,
+            'text' => BxTemplFunctions::getInstance()->getStringWithLimitedLength(strip_tags($aCmt['cmt_text']), $this->_sSnippetLenthLiveSearch),
+            'sample' => isset($aParams['txt_sample_single']) ? _t($aParams['txt_sample_single']) : ''
+        ));
+    }
+
+    function getFormBoxPost($aBp = array(), $aDp = array())
+    {
+        return $this->_getFormBox(BX_CMT_ACTION_POST, $aBp, $aDp);
+    }
+
+    function getFormBoxEdit($aBp = array(), $aDp = array())
+    {
+        return $this->_getFormBox(BX_CMT_ACTION_EDIT, $aBp, $aDp);
+    }
+
+    function getFormPost($iCmtParentId = 0, $aDp = array())
+    {
+        return $this->_getFormPost($iCmtParentId, $aDp);
+    }
+
+    function getFormEdit($iCmtId, $aDp = array())
+    {
+        return $this->_getFormEdit($iCmtId, $aDp);
+    }
+
+    function getControlsBox()
+    {
+        return $this->_getControlsBox();
+    }
+    
+    function getLiveUpdate($iCountOld = 0, $iCountNew = 0)
+    {
+        $iCount = (int)$iCountNew - (int)$iCountOld;
+        if($iCount < 0)
+            return '';
+
+        $aComments = $this->_oQuery->getCommentsBy(array('type' => 'latest', 'object_id' => $this->_iId, 'author' => $this->_getAuthorId(), 'others' => 1, 'start' => '0', 'per_page' => $iCount));
+        if(empty($aComments) || !is_array($aComments))
+            return '';
+
+        $aComment = array_shift($aComments);
+        if(empty($aComment) || !is_array($aComment))
+            return '';
+
+        $sJsObject = $this->getJsObjectName();
+        return $this->_oTemplate->parseHtmlByName('comments_lu_button.html', array(
+            'style_prefix' => $this->_sStylePrefix,
+            'html_id' => $this->getNotificationId(),
+            'onclick_show' => "javascript:" . $sJsObject . ".goToBtn(this, '" . $this->getItemAnchor($aComment['cmt_id']) . "', '" . $aComment['cmt_id'] . "');",
+        ));
+    }
+
+    function getLiveUpdates($iCountOld = 0, $iCountNew = 0)
+    {
+        $bShowAll = true;
+        $bShowActions = false;
+
+        $iCount = (int)$iCountNew - (int)$iCountOld;
+        if($iCount < 0)
+            return '';
+
+        $aComments = $this->_oQuery->getCommentsBy(array('type' => 'latest', 'object_id' => $this->_iId, 'author' => $this->_getAuthorId(), 'others' => 1, 'start' => '0', 'per_page' => $iCount));
+        if(empty($aComments) || !is_array($aComments))
+            return '';
+
+        $sJsObject = $this->getJsObjectName();
+
+        $iUserId = $this->_getAuthorId();
+        $bModerator = $this->isModerator();
+
+        $aComments = array_reverse($aComments);
+        $iComments = count($aComments);
+
+        $aTmplVarsNotifs = array();
+        foreach($aComments as $iIndex => $aComment) {
+            $iCommentId = $aComment['cmt_id'];
+
+            $sShowOnClick = "javascript:" . $sJsObject . ".goTo(this, '" .  $this->getItemAnchor($iCommentId) . "', '" . $iCommentId . "');";
+            $sReplyOnClick = "javascript:" . $sJsObject . ".goToAndReply(this, '" . $this->getItemAnchor($iCommentId) . "', '" . $iCommentId . "');";
+
+            $iAuthorId = (int)$aComment['cmt_author_id'];
+            if($iAuthorId < 0) {
+                if(abs($iAuthorId) == $iUserId)
+                    continue;
+                else if($bModerator)
+                    $iAuthorId *= -1;
+            }
+
+            $oAuthor = $this->_getAuthorObject($iAuthorId);
+            $sAuthorName = $oAuthor->getDisplayName();
+
+            $aTmplVarsNotifs[] = array(
+                'bx_if:show_as_hidden' => array(
+                    'condition' => !$bShowAll && $iIndex < ($iComments - 1),
+                    'content' => array(),
+                ),
+                'item' => $this->_oTemplate->parseHtmlByName('comments_lu_notifications.html', array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'onclick_show' => $sShowOnClick,
+                    'onclick_reply' => $sReplyOnClick,
+                    'author_link' => $oAuthor->getUrl(), 
+                    'author_title' => bx_html_attribute($sAuthorName),
+                    'author_name' => $sAuthorName,
+                    'author_unit' => $oAuthor->getUnit(0, array('template' => 'unit_wo_info_links')), 
+                    'text' => _t('_cmt_txt_added_sample')
+                )),
+                'bx_if:show_previous' => array(
+                    'condition' => $bShowActions && $iIndex > 0,
+                    'content' => array(
+                        'onclick_previous' => $sJsObject . '.previousLiveUpdate(this)'
+                    )
+                ),
+                'bx_if:show_close' => array(
+                    'condition' => $bShowActions,
+                    'content' => array(
+                        'onclick_close' => $sJsObject . '.hideLiveUpdate(this)'
+                    )
+                )
+            );
+        }
+
+        return $this->_oTemplate->parseHtmlByName('popup_chain.html', array(
+            'html_id' => $this->getNotificationId(),
+            'bx_repeat:items' => $aTmplVarsNotifs
+        ));
+    }
+
+    public function getElementBlock($aParams = array())
+    {
+        $aParams['usage'] = BX_CMT_USAGE_BLOCK;
+
+        return $this->getElement($aParams);
+    }
+
+    public function getElementInline($aParams = array())
+    {
+        $aParams['usage'] = BX_CMT_USAGE_INLINE;
+
+        return $this->getElement($aParams);
+    }
+
+    public function getElement($aParams = array())
+    {
+    	$aParams = array_merge($this->_aElementDefaults, $aParams);
+
+        $bShowDoCommentAsButtonSmall = isset($aParams['show_do_comment_as_button_small']) && $aParams['show_do_comment_as_button_small'] == true;
+        $bShowDoCommentAsButton = !$bShowDoCommentAsButtonSmall && isset($aParams['show_do_comment_as_button']) && $aParams['show_do_comment_as_button'] == true;
+        $bShowCounterEmpty = isset($aParams['show_counter_empty']) && $aParams['show_counter_empty'] == true;
+
+        $iObjectId = $this->getId();
+        $iAuthorId = $this->_getAuthorId();
+        $iAuthorIp = $this->_getAuthorIp();
+
+        $iCount = $this->getCommentsCountAll();
+        $bCount = (int)$iCount != 0;
+
+        $isAllowedComment = $this->isPostAllowed();
+
+        //--- Do Comment
+        $bTmplVarsDoComment = $this->_isShowDoComment($aParams, $isAllowedComment, $bCount);
+        $aTmplVarsDoComment = array();
+        if($bTmplVarsDoComment) {
+            $sClass = '';
+            if($bShowDoCommentAsButton)
+                $sClass = 'bx-btn';
+            else if ($bShowDoCommentAsButtonSmall)
+                $sClass = 'bx-btn bx-btn-small';
+
+            if(!$isAllowedComment)
+                $sClass .= $bShowDoCommentAsButton || $bShowDoCommentAsButtonSmall ? ' bx-btn-disabled' : 'bx-cmts-disabled';
+
+            $aTmplVarsDoComment = array(
+                'style_prefix' => $this->_sStylePrefix,
+                'do_comment' => $this->_oTemplate->parseLink($this->getListUrl(), $this->_getLabelDo($aParams), array(
+                    'class' => $this->_sStylePrefix . '-do-comment ' . $this->_sStylePrefix . '-dc ' . $sClass,
+                    'title' => _t($this->_getTitleDo())
+                )),
+            );
+        }
+
+        //--- Counter
+        $bTmplVarsCounter = $this->_isShowCounter($aParams, $isAllowedComment, $bCount);
+
+        $aTmplVarsCounter = array();
+        if($bTmplVarsCounter)
+            $aTmplVarsCounter = array(
+                'style_prefix' => $this->_sStylePrefix,
+                'bx_if:show_hidden' => array(
+                    'condition' => !$bShowCounterEmpty && !$bCount,
+                    'content' => array()
+                ),
+                'counter' => $this->getCounter($aParams)
+            );
+
+        if(!$bTmplVarsDoComment && !$bTmplVarsCounter)
+            return '';
+
+        $sTmplName = $this->{'_getTmplElement' . bx_gen_method_name(!empty($aParams['usage']) ? $aParams['usage'] : BX_CMT_USAGE_DEFAULT)}();
+        return $this->_oTemplate->parseHtmlByContent($sTmplName, array(
+            'style_prefix' => $this->_sStylePrefix,
+            'html_id' => $this->_aHtmlIds['main'],
+            'class' => $this->_sStylePrefix . ($bShowDoCommentAsButton ? '-button' : '') . ($bShowDoCommentAsButtonSmall ? '-button-small' : ''),
+            'count' => $iCount,
+            'bx_if:show_do_comment' => array(
+                'condition' => $bTmplVarsDoComment,
+                'content' => $aTmplVarsDoComment
+            ),
+            'bx_if:show_counter' => array(
+                'condition' => $bTmplVarsCounter,
+                'content' => $aTmplVarsCounter
+            ),
+            'script' => ''
+        ));
+    }
+
+    public function getCounter($aParams = array())
+    {
+        $bShowEmpty = isset($aParams['show_counter_empty']) && $aParams['show_counter_empty'] == true;
+        $bShowDoCommentAsButtonSmall = isset($aParams['show_do_comment_as_button_small']) && $aParams['show_do_comment_as_button_small'] == true;
+        $bShowDoCommentAsButton = !$bShowDoCommentAsButtonSmall && isset($aParams['show_do_comment_as_button']) && $aParams['show_do_comment_as_button'] == true;
+
+        $iCount = (int)$this->getCommentsCountAll();
+        if($iCount == 0 && !$bShowEmpty)
+            return '';
+
+        $sClass = $this->_sStylePrefix . '-counter';
+        if($bShowDoCommentAsButtonSmall)
+            $sClass .= ' bx-btn-small-height';
+        if($bShowDoCommentAsButton)
+            $sClass .= ' bx-btn-height';
+
+        $iCmtsLimit = 5;
+        $aCmts = $this->_oQuery->getCommentsBy(array('type' => 'object_id', 'object_id' => $this->getId(), 'order_way' => 'desc', 'start' => 0, 'per_page' => $iCmtsLimit * 4));
+        $aCmts = array_reverse($aCmts);
+
+        $aTmplVarsProfiles = array();
+        foreach($aCmts as $aCmt) {
+            $iAuthor = (int)$aCmt['cmt_author_id'];
+            if(array_key_exists($iAuthor, $aTmplVarsProfiles))
+                continue;
+
+            $oAuthor = BxDolProfile::getInstanceMagic($iAuthor);
+            if(!$oAuthor)
+                continue;
+
+            $aTmplVarsProfiles[$iAuthor] = array(
+                'icon' => $oAuthor->getUnit(0, array('template' => array('name' => 'unit_wo_info_links', 'size' => 'icon'))) 
+            );
+
+            if(count($aTmplVarsProfiles) >= $iCmtsLimit)
+                break;
+        }
+        $aTmplVarsProfiles = array_values($aTmplVarsProfiles);
+
+        $sHref = !empty($aParams['overwrite_counter_link_href']) ? $aParams['overwrite_counter_link_href'] : $this->getListUrl();
+        $sOnclick = '';
+        if(!empty($aParams['overwrite_counter_link_onclick']))
+            $sOnclick = $aParams['overwrite_counter_link_onclick'];
+
+        return $this->_oTemplate->parseHtmlByContent($this->_getTmplCounter(), array(
+            'id' => $this->_aHtmlIds['counter'],
+            'class' => $sClass,
+            'href' => $sHref,
+            'bx_if:show_onclick' => array(
+                'condition' => !empty($sOnclick),
+                'content' => array(
+                    'onclick' => $sOnclick
+                )
+            ),
+            'content' => $this->_getCounterLabel($iCount, $aParams),
+            'bx_repeat:profiles' => $aTmplVarsProfiles,
+            'bx_if:show_icon' => array(
+                'condition' => $bShowEmpty || !empty($aTmplVarsProfiles),
+                'content' => array(
+                    'icon' => isset($aParams['custom_icon']) && $aParams['custom_icon'] != '' ? $aParams['custom_icon'] : BxTemplFunctions::getInstanceWithTemplate($this->_oTemplate)->getFontIconAsHtml('comment', $this->_sStylePrefix . '-counter-icon sys-icon')
+                )
+            )
+        ));
+    }
+
+    protected function _getLabelDo($aParams = array())
+    {
+        return $this->_oTemplate->parseHtmlByContent($this->_getTmplLabelDo(), array(
+            'style_prefix' => $this->_sStylePrefix,
+            'bx_if:show_image' => array(
+                'condition' => isset($aParams['show_do_comment_image']) && $aParams['show_do_comment_image'] == true,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'src' => $this->_getImageDo()
+                )
+            ),
+            'bx_if:show_icon' => array(
+                'condition' => isset($aParams['show_do_comment_icon']) && $aParams['show_do_comment_icon'] == true,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'name' => $this->_getIconDo()
+                )
+            ),
+            'bx_if:show_text' => array(
+                'condition' => isset($aParams['show_do_comment_label']) && $aParams['show_do_comment_label'] == true,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'text' => _t($this->_getTitleDo())
+                )
+            )
+        ));
+    }
+
+    protected function _getCounterLabel($iCount, $aParams = array())
+    {
+        return (int)$iCount != 0 ? _t(isset($aParams['caption']) ? $aParams['caption'] : '_cmt_txt_counter', $iCount) : _t('_cmt_txt_counter_empty');
+    }
+
+    protected function _getTmplElementBlock()
+    {
+        return self::$_sTmplContentElementBlock;
+    }
+
+    protected function _getTmplElementInline()
+    {
+        return self::$_sTmplContentElementInline;
+    }
+
+    protected function _getTmplLabelDo()
+    {
+        return self::$_sTmplContentDoCommentLabel;
+    }
+
+    protected function _getTmplCounter()
+    {
+        return self::$_sTmplContentCounter;
+    }
+
+
+    /**
+     * private functions
+     */
+    protected function _getContentBefore($aBp = array(), $aDp = array())
+    {
+        return '';
+    }
+
+    protected function _getContentAfter($aBp = array(), $aDp = array())
+    {
+        return '';
+    }
+
+    protected function _getControlsBox()
+    {
+        $sDisplay = '';
+        $bDisplay = (int)$this->_aSystem['is_display_switch'] == 1;
+        if($bDisplay) {
+            $aDisplayLinks = array(
+                array('id' => $this->_sSystem . '-flat', 'name' => $this->_sSystem . '-flat', 'class' => '', 'title' => '_cmt_display_flat', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeDisplay(this, \'flat\');'),
+                array('id' => $this->_sSystem . '-threaded', 'name' => $this->_sSystem . '-threaded', 'class' => '', 'title' => '_cmt_display_threaded', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeDisplay(this, \'threaded\');')
+            );
+
+            $oMenu = new BxTemplMenuInteractive(array('template' => 'menu_interactive_vertical.html', 'menu_id'=> $this->_sSystem . '-display', 'menu_items' => $aDisplayLinks));
+            $oMenu->setSelected('', $this->_sSystem . '-' . $this->_sDisplayType);
+            $sDisplay = $oMenu->getCode();
+        }
+
+        $sBrowseType = '';
+        $bBrowseType = (int)$this->_aSystem['is_browse_switch'] == 1;
+        if($bBrowseType) {
+            $aBrowseLinks = array(
+                array('id' => $this->_sSystem . '-tail', 'name' => $this->_sSystem . '-tail', 'class' => '', 'title' => '_cmt_browse_tail', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeBrowse(this, \'tail\');'),
+                array('id' => $this->_sSystem . '-head', 'name' => $this->_sSystem . '-head', 'class' => '', 'title' => '_cmt_browse_head', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeBrowse(this, \'head\');'),
+                array('id' => $this->_sSystem . '-popular', 'name' => $this->_sSystem . '-popular', 'class' => '', 'title' => '_cmt_browse_popular', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeBrowse(this, \'popular\');'),
+            );
+
+            $oMenu = new BxTemplMenuInteractive(array('template' => 'menu_interactive_vertical.html', 'menu_id'=> $this->_sSystem . '-browse', 'menu_items' => $aBrowseLinks));
+            $oMenu->setSelected('', $this->_sSystem . '-' . $this->_sBrowseType);
+            $sBrowseType = $oMenu->getCode();
+        }
+
+        $sBrowseFilter = '';
+        $bBrowseFilter = (int)$this->_aSystem['is_browse_filter'] == 1;
+        if($bBrowseFilter) {
+            $aFilterLinks = array(
+                array('id' => $this->_sSystem . '-all', 'name' => $this->_sSystem . '-all', 'class' => '', 'title' => '_cmt_browse_all', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeFilter(this, \'all\');'),
+                array('id' => $this->_sSystem . '-friends', 'name' => $this->_sSystem . '-friends', 'class' => '', 'title' => '_cmt_browse_friends', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeFilter(this, \'friends\');'),
+                array('id' => $this->_sSystem . '-subscriptions', 'name' => $this->_sSystem . '-subscriptions', 'class' => '', 'title' => '_cmt_browse_subscriptions', 'target' => '_self', 'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtChangeFilter(this, \'subscriptions\');')
+            );
+
+            $oMenu = new BxTemplMenuInteractive(array('template' => 'menu_interactive_vertical.html', 'menu_id'=> $this->_sSystem . '-filter', 'menu_items' => $aFilterLinks));
+            $oMenu->setSelected('', $this->_sSystem . '-' . $this->_sBrowseFilter);
+            $sBrowseFilter = $oMenu->getCode();
+        }
+
+        return $this->_oTemplate->parseHtmlByName('comments_controls.html', array(
+            'display_switcher' => $bDisplay ? $sDisplay : '',
+            'bx_if:is_divider_1' => array(
+                'condition' => $bDisplay && $bBrowseType,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                )
+            ),
+            'browse_switcher' => $bBrowseType ? $sBrowseType : '',
+            'bx_if:is_divider_2' => array(
+                'condition' => $bBrowseType && $bBrowseFilter,
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                )
+            ),
+            'filter_switcher' => $bBrowseFilter ? $sBrowseFilter : '',
+        ));
+    }
+
+    protected function _getActionsBox(&$aCmt, $aDp = array())
+    {
+    	$bViewOnly = isset($aDp['view_only']) && $aDp['view_only'] === true;
+    	$bDynamicMode = isset($aDp['dynamic_mode']) && $aDp['dynamic_mode'] === true;
+
+        $sMenuActions = '';
+        if(!$bViewOnly) {
+            $oMenuActions = BxDolMenu::getObjectInstance($this->_sMenuObjActions);
+            $oMenuActions->setCmtsData($this, $aCmt['cmt_id']);
+            $oMenuActions->setDynamicMode($bDynamicMode);
+            $sMenuActions = $oMenuActions->getCode();
+        }
+
+        return $this->_oTemplate->parseHtmlByName('comment_actions.html', array(
+            'id' => $aCmt['cmt_id'],
+            'js_object' => $this->_sJsObjName,
+            'style_prefix' => $this->_sStylePrefix,
+            'menu_actions' => $sMenuActions,
+        ));
+    }
+
+    protected function _getFormBox($sType, $aBp, $aDp)
+    {
+        $iCmtParentId = isset($aBp['parent_id']) ? (int)$aBp['parent_id'] : 0;
+        $sPosition = isset($aDp['position']) ? $aDp['position'] : '';
+        $bQuote = isset($aDp['quote']) && (bool)$aDp['quote'];
+        $bFormMin = $iCmtParentId == 0 && isset($aDp['min_post_form']) && (bool)$aDp['min_post_form'];
+
+        $sPositionSystem = $this->_aSystem['post_form_position'];
+        if(!empty($sPosition) && $sPositionSystem != $sPosition)
+            return '';
+
+        $sClass = '';
+        if(!empty($sPosition))
+            $sClass .= ' ' . $this->_sStylePrefix . '-reply-' . $sPosition;
+        if($bQuote)
+            $sClass .= ' ' . $this->_sStylePrefix . '-reply-quote';
+        if($bFormMin)
+            $sClass .= ' ' . $this->_sStylePrefix . '-reply-min';
+        if(!empty($aDp['class']))
+            $sClass .= ' ' . $aDp['class'];
+
+        $sClassBody = '';
+        if(!empty($aDp['class_body']))
+            $sClassBody .= ' ' . $aDp['class_body'];
+
+        $aTmplVarsFormMin = array();
+        if($bFormMin) {
+            list($sAuthorName, $sAuthorLink, $sAuthorIcon, $sAuthorUnit) = $this->_getAuthorInfo($this->_getAuthorId());
+
+            $oForm = new BxTemplFormView(array());
+            $aInputPlaceholder = array(
+                'type' => 'text',
+                'name' => 'comment',
+                'caption' => '',
+                'attrs' => array(
+                    'onclick' => 'javascript:' . $this->_sJsObjName . '.cmtShowForm(this)',
+                    'placeholder' => _t($this->_aT['txt_min_form_placeholder'], $sAuthorName),
+                    'autocomplete' => 'off',
+                    'readonly' => 'readonly'
+                ),
+                'value' => '',
+            );
+
+            $sClassBodyMin = '';
+            if(!empty($aDp['class_body_min']))
+                $sClassBodyMin .= ' ' . $aDp['class_body_min'];
+
+            $aTmplVarsFormMin = array(
+                'js_object' => $this->_sJsObjName,
+                'class_body_min' => $sClassBodyMin,
+                'style_prefix' => $this->_sStylePrefix,
+                'author_unit' => $sAuthorUnit,
+                'placeholder' => $oForm->genRow($aInputPlaceholder)
+            );
+        }
+
+        $aForm = $this->{'_getForm' . ucfirst($sType)}($iCmtParentId, $aDp);
+        if(empty($aForm['form']))
+            return !empty($aForm['msg']) && (isLogged() || $iCmtParentId != 0 || $this->getCommentsCount() > 0) ? MsgBox($aForm['msg']) : '';
+
+        return $this->_oTemplate->parseHtmlByName('comment_reply_box.html', array(
+            'js_object' => $this->_sJsObjName,
+            'style_prefix' => $this->_sStylePrefix,
+            'class' => $sClass,
+            'class_body' => $sClassBody,
+            'bx_if:show_form_min' => array(
+                'condition' => $bFormMin,
+                'content' => $aTmplVarsFormMin
+            ),
+            'form' => $aForm['form'],
+            'form_id' => $aForm['form_id'],
+        ));
+    }
+
+    protected function _getFormAdd($aValues)
+    {
+        $iCmtAuthorId = isset($aValues['cmt_author_id']) ? (int)$aValues['cmt_author_id'] : $this->_getAuthorId();
+        $iCmtParentId = isset($aValues['cmt_parent_id']) ? (int)$aValues['cmt_parent_id'] : 0;
+
+        $oForm = $this->_getForm(BX_CMT_ACTION_POST, $iCmtParentId);
+        $oForm->aFormAttrs['method'] = BX_DOL_FORM_METHOD_SPECIFIC;
+        $oForm->aParams['csrf']['disable'] = true;
+        $oForm->aInputs['cmt_parent_id']['value'] = $iCmtParentId;
+        if(!empty($oForm->aParams['db']['submit_name'])) {            
+            $sSubmitName = false;
+            if(is_array($oForm->aParams['db']['submit_name']))
+                foreach($oForm->aParams['db']['submit_name'] as $sVal) {
+                    if(isset($oForm->aInputs[$sVal])) {
+                        $sSubmitName = $sVal;
+                        break;
+                    }
+                }
+            else
+                $sSubmitName = $oForm->aParams['db']['submit_name'];
+
+            if($sSubmitName && isset($oForm->aInputs[$sSubmitName]))
+                $aValues[$sSubmitName] = $oForm->aInputs[$sSubmitName]['value'];
+        }
+
+        $oForm->initChecker(array(), $aValues);
+        if(!$oForm->isSubmittedAndValid()) 
+            return array('code' => 1, 'message' => '_sys_txt_error_occured');
+
+        $iLevel = 0;
+        $iCmtVisualParentId = 0;
+        if((int)$iCmtParentId > 0) {
+            $aParent = $this->getCommentRow($iCmtParentId);
+
+            $iLevel = (int)$aParent['cmt_level'] + 1;
+            $iCmtVisualParentId = $iLevel > $this->getMaxLevel() ? $aParent['cmt_vparent_id'] : $iCmtParentId;
+        }
+
+        $iCmtId = (int)$oForm->insert(array('cmt_vparent_id' => $iCmtVisualParentId, 'cmt_object_id' => $this->_iId, 'cmt_author_id' => $iCmtAuthorId, 'cmt_level' => $iLevel, 'cmt_time' => time()));
+        if(!$iCmtId) {
+            if(!$oForm->isValid())
+                return array('code' => 1, 'message' => '_sys_txt_error_occured');
+            else
+                return array('code' => 2, 'message' => '_cmt_err_cannot_perform_action');
+        }
+
+        $iCmtUniqId = $this->_oQuery->getUniqId($this->_aSystem['system_id'], $iCmtId, $iCmtAuthorId);
+
+        if($iCmtParentId) {
+            $this->_oQuery->updateRepliesCount($iCmtParentId, 1);
+
+            if(!BxDolModuleQuery::getInstance()->isEnabledByName('bx_notifications'))
+                $this->_sendNotificationEmail($iCmtId, $iCmtParentId);
+        }
+
+        $this->_triggerComment();
+
+        if($this->_sMetatagsObj && ($oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj)) !== false)
+            $oMetatags->metaAdd($iCmtUniqId, $aValues['cmt_text']);
+
+        $mixedResult = $this->onPostAfter($iCmtId);
+        if($mixedResult === false)
+            return array('code' => 2, 'message' => '_cmt_err_cannot_perform_action');
+
+        return $mixedResult;
+    }
+
+    protected function _getFormPost($iCmtParentId = 0, $aDp = array())
+    {
+        $bCmtParentId = !empty($iCmtParentId);
+        if(!$bCmtParentId && !$this->isPostAllowed())
+            return array('msg' => $this->msgErrPostAllowed());
+
+        if($bCmtParentId && !$this->isReplyAllowed($iCmtParentId))
+            return array('msg' => $this->msgErrReplyAllowed());
+
+        $bDynamic = isset($aDp['dynamic_mode']) && (bool)$aDp['dynamic_mode'];
+        $bQuote = isset($aDp['quote']) && (bool)$aDp['quote'];
+
+        $oForm = $this->_getForm(BX_CMT_ACTION_POST, $iCmtParentId);
+        $oForm->aInputs['cmt_parent_id']['value'] = $iCmtParentId;
+
+        if($bQuote) {
+            $aCmtParent = $this->getCommentRow((int)$iCmtParentId);
+            if(!empty($aCmtParent['cmt_text']))
+                $oForm->aInputs['cmt_text']['value'] = $this->_oTemplate->parseHtmlByName('comment_quote.html', array(
+                    'content' => $aCmtParent['cmt_text']
+                ));
+        }
+
+        $oForm->initChecker();
+        if($oForm->isSubmittedAndValid()) {
+            $iCmtAuthorId = $this->_getAuthorId();
+            $iCmtParentId = (int)$oForm->getCleanValue('cmt_parent_id');
+            
+            //--- Process Text ---//
+            $sCmtText = $oForm->getCleanValue('cmt_text');
+            $bCmtText = !empty($sCmtText);
+
+            //--- Process Media ---//
+            $aImageIds = $oForm->getCleanValue('cmt_image');
+            $bImageIds = !empty($aImageIds) && is_array($aImageIds);
+
+            if(!$bCmtText && !$bImageIds) {
+                $oForm->aInputs['cmt_text']['error'] =  _t('_Please enter characters');
+                $oForm->setValid(false);
+
+            	return array('form' => $oForm->getCode($bDynamic), 'form_id' => $oForm->id);
+            }
+
+            $aParent = array();
+            if($iCmtParentId > 0) {
+                $aParent = $this->getCommentRow($iCmtParentId);
+                if(empty($aParent) || !is_array($aParent)) {
+                    $iCmtParentId = 0;
+                    $oForm->setSubmittedValue('cmt_parent_id', $iCmtParentId, $oForm->aFormAttrs['method']);
+                }
+            }
+
+            $iLevel = 0;
+            $iCmtVisualParentId = 0;
+            if($iCmtParentId > 0) {
+                $iLevel = (int)$aParent['cmt_level'] + 1;
+                $iCmtVisualParentId = $iLevel > $this->getMaxLevel() ? $aParent['cmt_vparent_id'] : $iCmtParentId;
+            }
+
+            $iCmtId = (int)$oForm->insert(array('cmt_vparent_id' => $iCmtVisualParentId, 'cmt_object_id' => $this->_iId, 'cmt_author_id' => $iCmtAuthorId, 'cmt_level' => $iLevel, 'cmt_time' => time()));
+            if($iCmtId != 0) {
+                $iCmtUniqId = $this->_oQuery->getUniqId($this->_aSystem['system_id'], $iCmtId, $iCmtAuthorId);
+
+                if($this->isAttachImageEnabled())
+                    $oForm->processImages($this, 'cmt_image', $iCmtUniqId, $iCmtId, $iCmtAuthorId, true);
+
+                if($iCmtParentId > 0) {
+                    $this->_oQuery->updateRepliesCount($iCmtParentId, 1);
+
+                    if(!BxDolModuleQuery::getInstance()->isEnabledByName('bx_notifications'))
+                        $this->_sendNotificationEmail($iCmtId, $iCmtParentId);
+                }
+
+                $this->_triggerComment();
+
+                if($iCmtParentId > 0)
+                    $this->isReplyAllowed($iCmtParentId, true);
+                else
+                    $this->isPostAllowed(true);
+
+                if($this->_sMetatagsObj && ($oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj)) !== false)
+                    $oMetatags->metaAdd($iCmtUniqId, $sCmtText);
+
+                if(($mixedResult = $this->onPostAfter($iCmtId)) !== false)
+                    return $mixedResult;
+            }
+
+            return array('msg' => _t('_cmt_err_cannot_perform_action'));
+        }
+
+        return array('form' => $oForm->getCode($bDynamic), 'form_id' => $oForm->id);
+    }
+
+    protected function _getFormEdit($iCmtId, $aDp = array())
+    {
+        $bDynamic = isset($aDp['dynamic_mode']) && (bool)$aDp['dynamic_mode'];
+
+        $aCmt = $this->getCommentSimple($iCmtId);
+        if(!$aCmt)
+            return array('msg' => _t('_No such comment'));
+
+        $iCmtAuthorId = $this->_getAuthorId();
+        if(!$this->isEditAllowed($aCmt))
+            return array('msg' => $aCmt['cmt_author_id'] == $iCmtAuthorId ? strip_tags($this->msgErrEditAllowed()) : _t('_Access denied'));
+
+        $oForm = $this->_getForm(BX_CMT_ACTION_EDIT, $aCmt['cmt_id']);
+
+        $oForm->initChecker($aCmt);
+        if($oForm->isSubmittedAndValid()) {
+            $sCmtText = $oForm->getCleanValue('cmt_text');
+
+            if($oForm->update($iCmtId) !== false) {
+                $iCmtUniqId = $this->_oQuery->getUniqId($this->_aSystem['system_id'], $iCmtId, (int)$aCmt['cmt_author_id']);
+
+                if($this->isAttachImageEnabled())
+                    $oForm->processImages($this, 'cmt_image', $iCmtUniqId, $iCmtId, $iCmtAuthorId, false);
+
+                $this->isEditAllowed($aCmt, true);
+
+                if($this->_sMetatagsObj && ($oMetatags = BxDolMetatags::getObjectInstance($this->_sMetatagsObj)) !== false)
+                    $oMetatags->metaAdd($iCmtUniqId, $sCmtText);
+
+                if(($mixedResult = $this->onEditAfter($iCmtId)) !== false)
+                    return $mixedResult;
+            }
+
+            return array('msg' => _t('_cmt_err_cannot_perform_action'));
+        }
+
+        return array('form' => $oForm->getCode($bDynamic), 'form_id' => $oForm->id);
+    }
+
+    protected function _getForm($sAction, $iId)
+    {
+        $oForm = $this->_getFormObject($sAction);
+        $oForm->setId(sprintf($oForm->getAttributeMask('id'), $sAction, $this->_sSystem, $this->_iId, $iId));
+        $oForm->setName(sprintf($oForm->getAttributeMask('name'), $sAction, $this->_sSystem, $this->_iId, $iId));
+        $oForm->aParams['db']['table'] = $this->_aSystem['table'];
+        $oForm->aInputs['sys']['value'] = $this->_sSystem;
+        $oForm->aInputs['id']['value'] = $this->_iId;
+        $oForm->aInputs['action']['value'] = 'Submit' . ucfirst($sAction) . 'Form';
+
+        if(!$this->isAttachImageEnabled())
+            unset($oForm->aInputs['cmt_image']);
+
+        if(isset($oForm->aInputs['cmt_text'])) {
+            $oForm->aInputs['cmt_text']['html'] = $this->_aSystem['html'];
+            $oForm->aInputs['cmt_text']['db']['pass'] = $this->isHtml() ? 'XssHtml' : 'XssMultiline';
+
+            if(isset($oForm->aInputs['cmt_text']['checker']['func']) && strtolower($oForm->aInputs['cmt_text']['checker']['func']) == 'length') {
+                $iCmtTextMin = (int)$this->_aSystem['chars_post_min'];
+                $iCmtTextMax = (int)$this->_aSystem['chars_post_max'];
+                $oForm->aInputs['cmt_text']['checker']['params'] = array($iCmtTextMin, $iCmtTextMax);
+                $oForm->aInputs['cmt_text']['checker']['error'] = _t('_Please enter n1-n2 characters', $iCmtTextMin, $iCmtTextMax);
+            }
+        }
+
+        if($sAction == BX_CMT_ACTION_EDIT && isset($oForm->aInputs['cmt_controls']))
+            foreach($oForm->aInputs['cmt_controls'] as $mixedKey => $mixedValue) {
+                if(!is_numeric($mixedKey) || empty($mixedValue['name']) || $mixedValue['name'] != 'cmt_cancel')
+                    continue;
+
+                if(!isset($oForm->aInputs['cmt_controls'][$mixedKey]['attrs']))
+                    $oForm->aInputs['cmt_controls'][$mixedKey]['attrs'] = array();
+
+                $oForm->aInputs['cmt_controls'][$mixedKey]['attrs']['onclick'] = $this->_sJsObjName . '.cmtEdit(this, ' . $iId . ', false)';
+            }
+
+        return $oForm;
+    }
+
+    protected function _getContent($aCmt)
+    {
+        $sAttachments = $this->_getAttachments($aCmt);
+
+        $sReactions = '';
+        if(($oReaction = $this->getReactionObject($aCmt['cmt_unique_id'])) !== false)
+            $sReactions = $oReaction->getCounter(array(
+                'show_counter' => true
+            ));
+
+        return $this->_oTemplate->parseHtmlByName($this->_sTmplNameItemContent, array_merge(array(
+            'style_prefix' => $this->_sStylePrefix,
+            'js_object' => $this->_sJsObjName,
+            'bx_if:show_attached' => array(
+                'condition' => !empty($sAttachments),
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'attached' => $sAttachments
+                )
+            ),
+            'reactions' => $sReactions,
+        ), $this->_getTmplVarsText($aCmt)));
+    }
+
+    protected function _getMoreLink($sCmts, $aBp = array(), $aDp = array())
+    {
+        $iStart = $iPerView = 0;
+        switch($aBp['type']) {
+            case BX_CMT_BROWSE_HEAD:
+            case BX_CMT_BROWSE_POPULAR:
+            case BX_CMT_BROWSE_CONNECTION:
+                $iPerView = $aBp['per_view'];
+
+                $iStart = $aBp['start'] + $iPerView;
+                if($iStart >= $aBp['count'])
+                    return $sCmts;
+
+                break;
+
+            case BX_CMT_BROWSE_TAIL:
+                $iPerView = $aBp['per_view'];
+
+                $iStart = $aBp['start'] - $iPerView;
+                if($iStart < 0) {
+                    $iPerView += $iStart;
+                    $iStart = 0;
+                }
+
+                if($iStart == 0 && $iPerView == 0)
+                    return $sCmts;
+
+                break;
+        }
+
+        $sParentKey = isset($aBp['vparent_id']) ? 'vparent_id' : 'parent_id';
+        $bRoot = (int)$aBp[$sParentKey] <= 0;
+
+        $sMore = $this->_oTemplate->parseHtmlByName('comment_more.html', array(
+            'js_object' => $this->_sJsObjName,
+            'style_prefix' => $this->_sStylePrefix,
+            'bx_if:is_root' => array(
+                'condition' => $bRoot,
+                'content' => array()
+            ),
+            'parent_id' => $aBp[$sParentKey],
+            'start' => $iStart,
+            'per_view' => $iPerView,
+            'title' => _t('_cmt_load_more_' . ($aBp[$sParentKey] == 0 ? 'comments' : 'replies') . '_' . $aBp['type'])
+        ));
+
+        switch($aBp['type']) {
+            case BX_CMT_BROWSE_HEAD:
+                case BX_CMT_BROWSE_POPULAR:
+                case BX_CMT_BROWSE_CONNECTION:
+                $sCmts .= $sMore;
+                break;
+
+            case BX_CMT_BROWSE_TAIL:
+                $sCmts = $sMore . $sCmts;
+                break;
+        }
+
+        return $sCmts;
+    }
+
+    protected function _getEmpty($aDp = array())
+    {
+        $sClass = '';
+        if(!empty($aDp['class']))
+            $sClass .= ' ' . $aDp['class'];
+
+        return $this->_oTemplate->parseHtmlByName('comment_empty.html', array(
+            'style_prefix' => $this->_sStylePrefix,
+            'class' => $sClass,
+            'content' => MsgBox(_t('_Empty'))
+        ));
+    }
+
+    protected function _getViewImagePopup()
+    {
+    	$sViewImagePopupId = 'cmts-box-' . $this->_sSystem . '-' . $this->getId() . '-view-image-popup' ;
+        $sViewImagePopupContent = $this->_oTemplate->parseHtmlByName('popup_image.html', array(
+            'image_url' => ''
+    	));
+
+    	return BxTemplFunctions::getInstance()->transBox($sViewImagePopupId, $sViewImagePopupContent, true);
+    }
+
+    protected function _getAttachments($aCmt)
+    {
+        $aTmplImages = array();
+        if(!$this->isAttachImageEnabled())
+            return ''; 
+
+        $aFiles = $this->_oQuery->getFiles($this->_aSystem['system_id'], $aCmt['cmt_id']);
+        if(!empty($aFiles) && is_array($aFiles)) {
+            $oStorage = BxDolStorage::getObjectInstance($this->getStorageObjectName());
+            $oTranscoder = BxDolTranscoderImage::getObjectInstance($this->getTranscoderPreviewName());
+
+            foreach($aFiles as $aFile) {
+                $bImage = $oTranscoder && $oTranscoder->isMimeTypeSupported($aFile['mime_type']);
+
+                $sPreview = '';
+                if($oTranscoder && $bImage)
+                    $sPreview = $oTranscoder->getFileUrl($aFile['image_id']);
+
+                if(!$sPreview)
+                    $sPreview = $this->_oTemplate->getIconUrl($oStorage->getIconNameByFileName($aFile['file_name']));
+
+                $aTmplVarsFile = array(
+                    'js_object' => $this->_sJsObjName,
+                    'preview' => $sPreview,
+                    'file' => $oStorage->getFileUrlById($aFile['image_id']),
+                    'file_name' => $aFile['file_name'],
+                    'file_icon' => $oStorage->getFontIconNameByFileName($aFile['file_name']),
+                    'file_size' => _t_format_size($aFile['size']),
+                );
+
+                $aTmplImages[] = array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'bx_if:show_image' => array(
+                        'condition' => $bImage,
+                        'content' => $aTmplVarsFile
+                    ),
+                    'bx_if:show_file' => array(
+                        'condition' => !$bImage,
+                        'content' => $aTmplVarsFile
+                    ),
+                );
+            }
+        }
+
+        return $this->_oTemplate->parseHtmlByName('comment_attachments.html', array(
+            'bx_repeat:attached' => $aTmplImages
+        ));
+    }
+
+    protected function _getTmplVarsAuthor($aCmt)
+    {
+    	list($sAuthorName, $sAuthorLink, $sAuthorIcon, $sAuthorUnit) = $this->_getAuthorInfo($aCmt['cmt_author_id']);
+    	$bAuthorIcon = !empty($sAuthorIcon);
+
+    	return array(
+    	    'author_unit' => $sAuthorUnit,
+            'bx_if:show_icon' => array(
+                'condition' => $bAuthorIcon,
+                'content' => array(
+                    'author_icon' => $sAuthorIcon
+                )
+            ),
+            'bx_if:show_icon_empty' => array(
+                'condition' => !$bAuthorIcon,
+                'content' => array()
+            ),
+            'bx_if:show_author_link' => array(
+                'condition' => !empty($sAuthorLink),
+                'content' => array(
+                    'author_link' => $sAuthorLink,
+            		'author_title' => bx_html_attribute($sAuthorName),
+                    'author_name' => $sAuthorName
+                )
+            ),
+            'bx_if:show_author_text' => array(
+                'condition' => empty($sAuthorLink),
+                'content' => array(
+                    'author_name' => $sAuthorName
+                )
+            ),
+    	);
+    }
+
+    protected function _getTmplVarsText($aCmt)
+    {
+    	$sText = $aCmt['cmt_text'];
+        $sTextMore = '';
+
+        if(!$this->isHtml()) {
+            $iMaxLength = (int)$this->_aSystem['chars_display_max'];
+            if(strlen($sText) > $iMaxLength) {
+                $iLength = strpos($sText, ' ', $iMaxLength);
+    
+                $sTextMore = trim(substr($sText, $iLength));
+                $sText = trim(substr($sText, 0, $iLength));
+            }
+        }
+
+        $sText = $this->_prepareTextForOutput($sText, $aCmt['cmt_id']);
+        $sTextMore = $this->_prepareTextForOutput($sTextMore, $aCmt['cmt_id']);
+
+        return array(
+			'text' => $sText,
+            'bx_if:show_more' => array(
+                'condition' => !empty($sTextMore),
+                'content' => array(
+                    'style_prefix' => $this->_sStylePrefix,
+                    'js_object' => $this->_sJsObjName,
+                    'text_more' => $sTextMore
+                )
+            ),
+        );
+    }
+}
+
+/** @} */

+ 220 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/files/template/scripts/BxBaseEditorQuill.php

@@ -0,0 +1,220 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    UnaBaseView UNA Base Representation Classes
+ * @{
+ */
+
+/**
+ * Quill editor representation.
+ * @see BxDolEditor
+ */
+class BxBaseEditorQuill extends BxDolEditor
+{
+    /**
+     * Common initialization params
+     */
+    
+    protected static $CONF_COMMON = "
+        var oParams = {              
+            skin: '{bx_var_skin}',
+            name: '{bx_var_editor_name}',
+            selector: '{bx_var_selector}',
+            css_class: '{bx_var_css_additional_class}',
+            toolbar: {toolbar},
+            root_url: '{bx_url_root}'
+        }
+        {bx_var_editor_name} = bx_editor_init({bx_var_editor_name}, oParams);";
+   
+    /**
+     * Standard view initialization params
+     */
+    protected static $CONF_STANDARD = "";
+
+    /**
+     * Minimal view initialization params
+     */
+    protected static $CONF_MINI = "";
+
+    /**
+     * Full view initialization params
+     */
+    protected static $CONF_FULL = "";
+
+    protected $_oTemplate;
+    protected $_bJsCssAdded = false;
+
+    public function __construct ($aObject, $oTemplate)
+    {
+        parent::__construct ($aObject);
+
+        if ($oTemplate)
+            $this->_oTemplate = $oTemplate;
+        else
+            $this->_oTemplate = BxDolTemplate::getInstance();
+    }
+
+    /**
+     * Attach editor to HTML element, in most cases - textarea.
+     * @param $sSelector - jQuery selector to attach editor to.
+     * @param $iViewMode - editor view mode: BX_EDITOR_STANDARD, BX_EDITOR_MINI, BX_EDITOR_FULL
+     * @param $bDynamicMode - is AJAX mode or not, the HTML with editor area is loaded dynamically.
+     */
+    public function attachEditor ($sSelector, $iViewMode = BX_EDITOR_STANDARD, $bDynamicMode = false, $aAttrs = [])
+    {
+        // set visual mode
+        switch ($iViewMode) {
+        case BX_EDITOR_MINI:
+                $sToolbarItems = getParam('sys_quill_toolbar_mini');
+                $sCustomInit = self::$CONF_MINI;
+                break;
+                
+            case BX_EDITOR_FULL:
+                $sToolbarItems = getParam('sys_quill_toolbar_full');
+                $sCustomInit = self::$CONF_FULL;
+            break;
+                
+            case BX_EDITOR_STANDARD:
+            default:
+                $sToolbarItems = getParam('sys_quill_toolbar_standard');
+                $sCustomInit = self::$CONF_STANDARD;
+        }
+        
+        if ($this->_sButtonsCustom !== false) {
+            $sToolbarItems = $this->_sButtonsCustom;
+        }
+        
+        $sCss = 'editor.less';
+        $aCss = BxDolTemplate::getInstance()->_lessCss(array(
+        	'path' => $this->_oTemplate->getCssPath($sCss),
+        	'url' => $this->_oTemplate->getCssUrl($sCss)
+        ));
+        
+        $sEditorName = 'quill_' . str_replace(['-', ' '], '_', $aAttrs['form_id'] . '_' . $aAttrs['element_name']);
+        $this->_oTemplate->addJsTranslation([
+            '_sys_txt_quill_tooltip_bold',
+            '_sys_txt_quill_tooltip_italic',
+            '_sys_txt_quill_tooltip_underline',
+            '_sys_txt_quill_tooltip_clean',
+            '_sys_txt_quill_tooltip_list_ordered',
+            '_sys_txt_quill_tooltip_list_bullet',
+            '_sys_txt_quill_tooltip_indent_1',
+            '_sys_txt_quill_tooltip_indent_2',
+            '_sys_txt_quill_tooltip_blockquote',
+            '_sys_txt_quill_tooltip_direction',
+            '_sys_txt_quill_tooltip_script_sub',
+            '_sys_txt_quill_tooltip_script_super',
+            '_sys_txt_quill_tooltip_link',
+            '_sys_txt_quill_tooltip_image',
+            '_sys_txt_quill_tooltip_code_block',
+            '_sys_txt_quill_tooltip_color',
+            '_sys_txt_quill_tooltip_background',
+            '_sys_txt_quill_tooltip_align',
+            '_sys_txt_quill_tooltip_header',
+            '_sys_txt_quill_tooltip_embed',
+            '_sys_txt_quill_tooltip_embed_popup_header',
+            '_sys_txt_quill_tooltip_link_popup_header',
+        ]);
+        // initialize editor
+        $sInitEditor = $this->_replaceMarkers(self::$CONF_COMMON, array(
+            'bx_var_custom_init' => $sCustomInit,
+            'bx_var_selector' => bx_js_string($sSelector, BX_ESCAPE_STR_APOS),
+            'bx_var_form_id' => $aAttrs['form_id'],
+            'toolbar' => $sToolbarItems ? '[' . $sToolbarItems . ']' : 'false',
+            'bx_var_css_additional_class' => $sToolbarItems ? '' : 'bx-form-input-html-quill-empty',
+            'bx_var_element_name' => str_replace(['-', ' '], '_', $aAttrs['element_name']),
+            'bx_var_editor_name' => $sEditorName,
+            'bx_var_skin' => bx_js_string($this->_aObject['skin'], BX_ESCAPE_STR_APOS),
+            'bx_url_root' => bx_js_string(BX_DOL_URL_ROOT, BX_ESCAPE_STR_APOS),
+            'bx_var_css_path' => bx_js_string($aCss['url'], BX_ESCAPE_STR_APOS),
+        ));
+
+        if ($bDynamicMode) {
+
+            list($aJs, $aCss) = $this->_getJsCss(true);
+            $sCss = $this->_oTemplate->addCss($aCss, true);
+            
+            $sScript = $sCss . "<script>
+                var " . $sEditorName . ";
+                if (typeof bQuillEditorInited === 'undefined') {
+                    bx_get_scripts(" . json_encode($aJs) . ", function () {
+                        bQuillEditorInited = true;
+                        Quill.register('modules/imageUploader', ImageUploader); 
+                        $sInitEditor
+                    });
+                } else {
+                	setTimeout(function () {
+                    	$sInitEditor
+                    }, 10); // wait while html is rendered in case of dynamic adding html with quill
+                } 
+                if (typeof bQuillEditorInited === 'undefined') 
+                    bQuillEditorInited = true;
+            </script>";
+
+        } else {
+
+            $sScript = "
+            <script>
+                var " . $sEditorName . ";
+                $(document).ready(function () {
+                    Quill.register('modules/imageUploader', ImageUploader); 
+                    $sInitEditor
+                });
+            </script>";
+        }
+
+        return $this->_addJsCss($bDynamicMode) . $sScript;
+    }
+    
+
+    /**
+     * Add css/js files which are needed for editor display and functionality.
+     */
+    protected function _addJsCss($bDynamicMode = false, $sInitEditor = '')
+    {
+        if ($bDynamicMode)
+            return '';
+        
+        if ($this->_bJsCssAdded)
+            return '';
+        
+        list($aJs, $aCss) = $this->_getJsCss();
+
+        $this->_oTemplate->addJs($aJs);
+        $this->_oTemplate->addCss($aCss);
+        
+        $this->_bJsCssAdded = true;
+        
+        return '';
+    }
+    
+    protected function _getJsCss($bUseUrlsForJs = false)
+    {
+        $sJsPrefix = $bUseUrlsForJs ? BX_DOL_URL_PLUGINS_PUBLIC : BX_DIRECTORY_PATH_PLUGINS_PUBLIC;
+        $sJsPrefixRoot = $bUseUrlsForJs ? BX_DOL_URL_ROOT .'inc/js/' : BX_DIRECTORY_PATH_INC . 'js/';
+        $sJsSuffix = $bUseUrlsForJs ? '' : '|';
+        
+        $aJs = array(
+            $sJsPrefix . 'highlight/' . $sJsSuffix . 'highlight.min.js',
+            $sJsPrefix . 'quill/' . $sJsSuffix . 'quill.min.js', 
+            $sJsPrefix . 'quill/' . $sJsSuffix . 'quill.mention.js',  
+            $sJsPrefix . 'quill/' . $sJsSuffix . 'quill.imageUploader.min.js', 
+            $sJsPrefix . 'quill/' . $sJsSuffix . 'image-resize.min.js', 
+            $sJsPrefixRoot  . $sJsSuffix . 'editor.quill.js',
+        );
+
+        $aCss = array(
+            BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'quill/|quill.' . $this->_aObject['skin'] . '.css',  
+            BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'quill/|quill.mention.css', 
+            BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'highlight/|default.min.css',
+            BX_DIRECTORY_PATH_PLUGINS_PUBLIC . 'quill/quill.imageUploader.min.css',
+            BX_DIRECTORY_PATH_BASE . 'css/|editor.quill.css',
+        );
+
+        return array($aJs, $aCss);
+    }
+}
+
+/** @} */

+ 3 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/script.php

@@ -0,0 +1,3 @@
+<?php
+
+    return true;

+ 23 - 0
upgrade/files/13.0.0.A1-13.0.0.A2/sql.sql

@@ -0,0 +1,23 @@
+
+-- Options
+
+UPDATE `sys_options` SET `type` = 'digit' WHERE `name` = 'sys_editor_default';
+UPDATE `sys_options` SET `value` = 'sys_quill' WHERE `name` = 'sys_editor_default' AND `value` IN('sys_recaptcha_new', 'sys_recaptcha_invisible', 'sys_hcaptcha', 'sys_recaptcha', '');
+
+-- Forms
+
+UPDATE `sys_objects_form` SET `form_attrs` = 'a:3:{s:2:"id";s:20:"cmt-%s-form-%s-%d-%d";s:4:"name";s:20:"cmt-%s-form-%s-%d-%d";s:5:"class";s:14:"cmt-post-reply";}' WHERE `object` = 'sys_comment';
+UPDATE `sys_objects_form` SET `form_attrs` = 'a:3:{s:2:"id";s:20:"cmt-%s-form-%s-%d-%d";s:4:"name";s:20:"cmt-%s-form-%s-%d-%d";s:5:"class";s:14:"cmt-post-reply";}' WHERE `object` = 'sys_review';
+
+-- Forms fields
+
+UPDATE `sys_form_inputs` SET `value` = '', `values` = '' WHERE `object` IN('sys_comment','sys_review') AND `name` IN('sys', 'id', 'action', 'cmt_id', 'cmt_parent_id', 'cmt_text', 'cmt_anonymous', 'cmt_mood');
+UPDATE `sys_form_inputs` SET `value` = '', `values` = 'cmt_submit,cmt_cancel' WHERE `object` IN('sys_comment') AND `name` IN('cmt_controls');
+UPDATE `sys_form_inputs` SET `value` = '_sys_form_comment_input_cancel', `values` = '' WHERE `object` IN('sys_comment') AND `name` IN('cmt_cancel');
+UPDATE `sys_form_inputs` SET `value` = '_sys_form_comment_input_submit', `values` = '' WHERE `object` IN('sys_comment') AND `name` IN('cmt_submit');
+UPDATE `sys_form_inputs` SET `value` = '_sys_form_review_input_submit', `values` = '' WHERE `object` IN('sys_review') AND `name` IN('cmt_submit');
+
+-- Last step is to update current version
+
+UPDATE `sys_modules` SET `version` = '13.0.0-A2' WHERE (`version` = '13.0.0.A1' OR `version` = '13.0.0-A1') AND `name` = 'system';
+

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio