form_utils.js000064400000013673147207073150007305 0ustar00/** * form_utils.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme")); function getColorPickerHTML(id, target_form_element) { var h = "", dom = tinyMCEPopup.dom; if (label = dom.select('label[for=' + target_form_element + ']')[0]) { label.id = label.id || dom.uniqueId(); } h += ''; h += ' '; return h; } function updateColor(img_id, form_element_id) { document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; } function setBrowserDisabled(id, state) { var img = document.getElementById(id); var lnk = document.getElementById(id + "_link"); if (lnk) { if (state) { lnk.setAttribute("realhref", lnk.getAttribute("href")); lnk.removeAttribute("href"); tinyMCEPopup.dom.addClass(img, 'disabled'); } else { if (lnk.getAttribute("realhref")) { lnk.setAttribute("href", lnk.getAttribute("realhref")); } tinyMCEPopup.dom.removeClass(img, 'disabled'); } } } function getBrowserHTML(id, target_form_element, type, prefix) { var option = prefix + "_" + type + "_browser_callback", cb, html; cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); if (!cb) { return ""; } html = ""; html += ''; html += ' '; return html; } function openBrowser(img_id, target_form_element, type, option) { var img = document.getElementById(img_id); if (img.className != "mceButtonDisabled") { tinyMCEPopup.openBrowser(target_form_element, type, option); } } function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { if (!form_obj || !form_obj.elements[field_name]) { return; } if (!value) { value = ""; } var sel = form_obj.elements[field_name]; var found = false; for (var i = 0; i < sel.options.length; i++) { var option = sel.options[i]; if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { option.selected = true; found = true; } else { option.selected = false; } } if (!found && add_custom && value != '') { var option = new Option(value, value); option.selected = true; sel.options[sel.options.length] = option; sel.selectedIndex = sel.options.length - 1; } return found; } function getSelectValue(form_obj, field_name) { var elm = form_obj.elements[field_name]; if (elm == null || elm.options == null || elm.selectedIndex === -1) { return ""; } return elm.options[elm.selectedIndex].value; } function addSelectValue(form_obj, field_name, name, value) { var s = form_obj.elements[field_name]; var o = new Option(name, value); s.options[s.options.length] = o; } function addClassesToList(list_id, specific_option) { // Setup class droplist var styleSelectElm = document.getElementById(list_id); var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); styles = tinyMCEPopup.getParam(specific_option, styles); if (styles) { var stylesAr = styles.split(';'); for (var i = 0; i < stylesAr.length; i++) { if (stylesAr != "") { var key, value; key = stylesAr[i].split('=')[0]; value = stylesAr[i].split('=')[1]; styleSelectElm.options[styleSelectElm.length] = new Option(key, value); } } } else { /*tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); });*/ } } function isVisible(element_id) { var elm = document.getElementById(element_id); return elm && elm.style.display != "none"; } function convertRGBToHex(col) { var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); var rgb = col.replace(re, "$1,$2,$3").split(','); if (rgb.length == 3) { r = parseInt(rgb[0]).toString(16); g = parseInt(rgb[1]).toString(16); b = parseInt(rgb[2]).toString(16); r = r.length == 1 ? '0' + r : r; g = g.length == 1 ? '0' + g : g; b = b.length == 1 ? '0' + b : b; return "#" + r + g + b; } return col; } function convertHexToRGB(col) { if (col.indexOf('#') != -1) { col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); r = parseInt(col.substring(0, 2), 16); g = parseInt(col.substring(2, 4), 16); b = parseInt(col.substring(4, 6), 16); return "rgb(" + r + "," + g + "," + b + ")"; } return col; } function trimSize(size) { return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); } function getCSSSize(size) { size = trimSize(size); if (size == "") { return ""; } // Add px if (/^[0-9]+$/.test(size)) { size += 'px'; } // Confidence check, IE doesn't like broken values else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) { return ""; } return size; } function getStyle(elm, attrib, style) { var val = tinyMCEPopup.dom.getAttrib(elm, attrib); if (val != '') { return '' + val; } if (typeof (style) == 'undefined') { style = attrib; } return tinyMCEPopup.dom.getStyle(elm, style); } editable_selects.js000064400000004115147207073150010404 0ustar00/** * editable_selects.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var TinyMCE_EditableSelects = { editSelectElm : null, init : function () { var nl = document.getElementsByTagName("select"), i, d = document, o; for (i = 0; i < nl.length; i++) { if (nl[i].className.indexOf('mceEditableSelect') != -1) { o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); o.className = 'mceAddSelectValue'; nl[i].options[nl[i].options.length] = o; nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; } } }, onChangeEditableSelect : function (e) { var d = document, ne, se = window.event ? window.event.srcElement : e.target; if (se.options[se.selectedIndex].value == '__mce_add_custom__') { ne = d.createElement("input"); ne.id = se.id + "_custom"; ne.name = se.name + "_custom"; ne.type = "text"; ne.style.width = se.offsetWidth + 'px'; se.parentNode.insertBefore(ne, se); se.style.display = 'none'; ne.focus(); ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; TinyMCE_EditableSelects.editSelectElm = se; } }, onBlurEditableSelectInput : function () { var se = TinyMCE_EditableSelects.editSelectElm; if (se) { if (se.previousSibling.value != '') { addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); selectByValue(document.forms[0], se.id, se.previousSibling.value); } else { selectByValue(document.forms[0], se.id, ''); } se.style.display = 'inline'; se.parentNode.removeChild(se.previousSibling); TinyMCE_EditableSelects.editSelectElm = null; } }, onKeyDown : function (e) { e = e || window.event; if (e.keyCode == 13) { TinyMCE_EditableSelects.onBlurEditableSelectInput(); } } }; validate.js000064400000014502147207073150006703 0ustar00/** * validate.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ /** // String validation: if (!Validator.isEmail('myemail')) alert('Invalid email.'); // Form validation: var f = document.forms['myform']; if (!Validator.isEmail(f.myemail)) alert('Invalid email.'); */ var Validator = { isEmail : function (s) { return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); }, isAbsUrl : function (s) { return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); }, isSize : function (s) { return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); }, isId : function (s) { return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); }, isEmpty : function (s) { var nl, i; if (s.nodeName == 'SELECT' && s.selectedIndex < 1) { return true; } if (s.type == 'checkbox' && !s.checked) { return true; } if (s.type == 'radio') { for (i = 0, nl = s.form.elements; i < nl.length; i++) { if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) { return false; } } return true; } return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); }, isNumber : function (s, d) { return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); }, test : function (s, p) { s = s.nodeType == 1 ? s.value : s; return s == '' || new RegExp(p).test(s); } }; var AutoValidator = { settings : { id_cls : 'id', int_cls : 'int', url_cls : 'url', number_cls : 'number', email_cls : 'email', size_cls : 'size', required_cls : 'required', invalid_cls : 'invalid', min_cls : 'min', max_cls : 'max' }, init : function (s) { var n; for (n in s) { this.settings[n] = s[n]; } }, validate : function (f) { var i, nl, s = this.settings, c = 0; nl = this.tags(f, 'label'); for (i = 0; i < nl.length; i++) { this.removeClass(nl[i], s.invalid_cls); nl[i].setAttribute('aria-invalid', false); } c += this.validateElms(f, 'input'); c += this.validateElms(f, 'select'); c += this.validateElms(f, 'textarea'); return c == 3; }, invalidate : function (n) { this.mark(n.form, n); }, getErrorMessages : function (f) { var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; nl = this.tags(f, "label"); for (i = 0; i < nl.length; i++) { if (this.hasClass(nl[i], s.invalid_cls)) { field = document.getElementById(nl[i].getAttribute("for")); values = { field: nl[i].textContent }; if (this.hasClass(field, s.min_cls, true)) { message = ed.getLang('invalid_data_min'); values.min = this.getNum(field, s.min_cls); } else if (this.hasClass(field, s.number_cls)) { message = ed.getLang('invalid_data_number'); } else if (this.hasClass(field, s.size_cls)) { message = ed.getLang('invalid_data_size'); } else { message = ed.getLang('invalid_data'); } message = message.replace(/{\#([^}]+)\}/g, function (a, b) { return values[b] || '{#' + b + '}'; }); messages.push(message); } } return messages; }, reset : function (e) { var t = ['label', 'input', 'select', 'textarea']; var i, j, nl, s = this.settings; if (e == null) { return; } for (i = 0; i < t.length; i++) { nl = this.tags(e.form ? e.form : e, t[i]); for (j = 0; j < nl.length; j++) { this.removeClass(nl[j], s.invalid_cls); nl[j].setAttribute('aria-invalid', false); } } }, validateElms : function (f, e) { var nl, i, n, s = this.settings, st = true, va = Validator, v; nl = this.tags(f, e); for (i = 0; i < nl.length; i++) { n = nl[i]; this.removeClass(n, s.invalid_cls); if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) { st = this.mark(f, n); } if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.size_cls) && !va.isSize(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.id_cls) && !va.isId(n)) { st = this.mark(f, n); } if (this.hasClass(n, s.min_cls, true)) { v = this.getNum(n, s.min_cls); if (isNaN(v) || parseInt(n.value) < parseInt(v)) { st = this.mark(f, n); } } if (this.hasClass(n, s.max_cls, true)) { v = this.getNum(n, s.max_cls); if (isNaN(v) || parseInt(n.value) > parseInt(v)) { st = this.mark(f, n); } } } return st; }, hasClass : function (n, c, d) { return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); }, getNum : function (n, c) { c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; c = c.replace(/[^0-9]/g, ''); return c; }, addClass : function (n, c, b) { var o = this.removeClass(n, c); n.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c; }, removeClass : function (n, c) { c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); return n.className = c !== ' ' ? c : ''; }, tags : function (f, s) { return f.getElementsByTagName(s); }, mark : function (f, n) { var s = this.settings; this.addClass(n, s.invalid_cls); n.setAttribute('aria-invalid', 'true'); this.markLabels(f, n, s.invalid_cls); return false; }, markLabels : function (f, n, ic) { var nl, i; nl = this.tags(f, "label"); for (i = 0; i < nl.length; i++) { if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) { this.addClass(nl[i], ic); } } return null; } }; mctabs.js000064400000010100147207073150006351 0ustar00/** * mctabs.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ /*jshint globals: tinyMCEPopup */ function MCTabs() { this.settings = []; this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); } MCTabs.prototype.init = function (settings) { this.settings = settings; }; MCTabs.prototype.getParam = function (name, default_value) { var value = null; value = (typeof (this.settings[name]) == "undefined") ? default_value : this.settings[name]; // Fix bool values if (value == "true" || value == "false") { return (value == "true"); } return value; }; MCTabs.prototype.showTab = function (tab) { tab.className = 'current'; tab.setAttribute("aria-selected", true); tab.setAttribute("aria-expanded", true); tab.tabIndex = 0; }; MCTabs.prototype.hideTab = function (tab) { var t = this; tab.className = ''; tab.setAttribute("aria-selected", false); tab.setAttribute("aria-expanded", false); tab.tabIndex = -1; }; MCTabs.prototype.showPanel = function (panel) { panel.className = 'current'; panel.setAttribute("aria-hidden", false); }; MCTabs.prototype.hidePanel = function (panel) { panel.className = 'panel'; panel.setAttribute("aria-hidden", true); }; MCTabs.prototype.getPanelForTab = function (tabElm) { return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); }; MCTabs.prototype.displayTab = function (tab_id, panel_id, avoid_focus) { var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; tabElm = document.getElementById(tab_id); if (panel_id === undefined) { panel_id = t.getPanelForTab(tabElm); } panelElm = document.getElementById(panel_id); panelContainerElm = panelElm ? panelElm.parentNode : null; tabContainerElm = tabElm ? tabElm.parentNode : null; selectionClass = t.getParam('selection_class', 'current'); if (tabElm && tabContainerElm) { nodes = tabContainerElm.childNodes; // Hide all other tabs for (i = 0; i < nodes.length; i++) { if (nodes[i].nodeName == "LI") { t.hideTab(nodes[i]); } } // Show selected tab t.showTab(tabElm); } if (panelElm && panelContainerElm) { nodes = panelContainerElm.childNodes; // Hide all other panels for (i = 0; i < nodes.length; i++) { if (nodes[i].nodeName == "DIV") { t.hidePanel(nodes[i]); } } if (!avoid_focus) { tabElm.focus(); } // Show selected panel t.showPanel(panelElm); } }; MCTabs.prototype.getAnchor = function () { var pos, url = document.location.href; if ((pos = url.lastIndexOf('#')) != -1) { return url.substring(pos + 1); } return ""; }; //Global instance var mcTabs = new MCTabs(); tinyMCEPopup.onInit.add(function () { var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; each(dom.select('div.tabs'), function (tabContainerElm) { //var keyNav; dom.setAttrib(tabContainerElm, "role", "tablist"); var items = tinyMCEPopup.dom.select('li', tabContainerElm); var action = function (id) { mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); mcTabs.onChange.dispatch(id); }; each(items, function (item) { dom.setAttrib(item, 'role', 'tab'); dom.bind(item, 'click', function (evt) { action(item.id); }); }); dom.bind(dom.getRoot(), 'keydown', function (evt) { if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab //keyNav.moveFocus(evt.shiftKey ? -1 : 1); tinymce.dom.Event.cancel(evt); } }); each(dom.select('a', tabContainerElm), function (a) { dom.setAttrib(a, 'tabindex', '-1'); }); /*keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { root: tabContainerElm, items: items, onAction: action, actOnFocus: true, enableLeftRight: true, enableUpDown: true }, tinyMCEPopup.dom);*/ } ); });svg/svg-sanitizer.php000064400000034403147207256750010704 0ustar00is_encoded( $original_content ); if ( $is_encoded ) { $decoded = $this->decode_svg( $original_content ); if ( false === $decoded ) { return false; } $original_content = $decoded; } $valid_svg = $this->sanitize( $original_content ); if ( false === $valid_svg ) { return false; } // If we were gzipped, we need to re-zip if ( $is_encoded ) { $valid_svg = $this->encode_svg( $valid_svg ); } file_put_contents( $filename, $valid_svg ); return true; } /** * Sanitize * * @since 3.16.0 * @access public * * @param $content * @return bool|string */ public function sanitize( $content ) { // Strip php tags $content = $this->strip_comments( $content ); $content = $this->strip_php_tags( $content ); $content = $this->strip_line_breaks( $content ); // Find the start and end tags so we can cut out miscellaneous garbage. $start = strpos( $content, '' ); if ( false === $start || false === $end ) { return false; } $content = substr( $content, $start, ( $end - $start + 6 ) ); // If the server's PHP version is 8 or up, make sure to Disable the ability to load external entities $php_version_under_eight = version_compare( PHP_VERSION, '8.0.0', '<' ); if ( $php_version_under_eight ) { $libxml_disable_entity_loader = libxml_disable_entity_loader( true ); // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated } // Suppress the errors $libxml_use_internal_errors = libxml_use_internal_errors( true ); // Create DomDocument instance $this->svg_dom = new \DOMDocument(); $this->svg_dom->formatOutput = false; $this->svg_dom->preserveWhiteSpace = false; $this->svg_dom->strictErrorChecking = false; $open_svg = $this->svg_dom->loadXML( $content ); if ( ! $open_svg ) { return false; } $this->strip_doctype(); $this->sanitize_elements(); // Export sanitized svg to string // Using documentElement to strip out svg_dom->saveXML( $this->svg_dom->documentElement, LIBXML_NOEMPTYTAG ); // Restore defaults if ( $php_version_under_eight ) { libxml_disable_entity_loader( $libxml_disable_entity_loader ); // phpcs:ignore Generic.PHP.DeprecatedFunctions.Deprecated } libxml_use_internal_errors( $libxml_use_internal_errors ); return $sanitized; } /** * Is Encoded * * Check if the contents of the SVG file are gzipped * @see http://www.gzip.org/zlib/rfc-gzip.html#member-format * * @since 3.16.0 * @access private * * @param $contents * * @return bool */ private function is_encoded( $contents ) { $needle = "\x1f\x8b\x08"; if ( function_exists( 'mb_strpos' ) ) { return 0 === mb_strpos( $contents, $needle ); } else { return 0 === strpos( $contents, $needle ); } } /** * Encode SVG * * @since 3.16.0 * @access private * * @param $content * @return string */ private function encode_svg( $content ) { return gzencode( $content ); } /** * Decode SVG * * @since 3.16.0 * @access private * * @param $content * * @return string */ private function decode_svg( $content ) { return gzdecode( $content ); } /** * Is Allowed Tag * * @since 3.16.0 * @access private * * @param $element * @return bool */ private function is_allowed_tag( $element ) { static $allowed_tags = false; if ( false === $allowed_tags ) { $allowed_tags = $this->get_allowed_elements(); } $tag_name = $element->tagName; // phpcs:ignore -- php DomDocument if ( ! in_array( strtolower( $tag_name ), $allowed_tags ) ) { $this->remove_element( $element ); return false; } return true; } /** * Remove Element * * Removes the passed element from its DomDocument tree * * @since 3.16.0 * @access private * * @param $element */ private function remove_element( $element ) { $element->parentNode->removeChild( $element ); // phpcs:ignore -- php DomDocument } /** * Is It An Attribute * * @since 3.16.0 * @access private * * @param $name * @param $check * @return bool */ private function is_a_attribute( $name, $check ) { return 0 === strpos( $name, $check . '-' ); } /** * Is Remote Value * * @since 3.16.0 * @access private * * @param $value * @return string */ private function is_remote_value( $value ) { $value = trim( preg_replace( '/[^ -~]/xu', '', $value ) ); $wrapped_in_url = preg_match( '~^url\(\s*[\'"]\s*(.*)\s*[\'"]\s*\)$~xi', $value, $match ); if ( ! $wrapped_in_url ) { return false; } $value = trim( $match[1], '\'"' ); return preg_match( '~^((https?|ftp|file):)?//~xi', $value ); } /** * Has JS Value * * @since 3.16.0 * @access private * * @param $value * @return false|int */ private function has_js_value( $value ) { return preg_match( '/base64|data|(?:java)?script|alert\(|window\.|document/i', $value ); } /** * Get Allowed Attributes * * Returns an array of allowed tag attributes in SVG files. * * @since 3.16.0 * @access private * * @return array */ private function get_allowed_attributes() { $allowed_attributes = [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemlanguage', 'transform', 'href', 'xlink:href', 'xlink:title', 'cx', 'cy', 'r', 'requiredfeatures', 'clippathunits', 'type', 'rx', 'ry', 'color-interpolation-filters', 'stddeviation', 'filterres', 'filterunits', 'height', 'primitiveunits', 'width', 'x', 'y', 'font-size', 'display', 'font-family', 'font-style', 'font-weight', 'text-anchor', 'marker-end', 'marker-mid', 'marker-start', 'x1', 'x2', 'y1', 'y2', 'gradienttransform', 'gradientunits', 'spreadmethod', 'markerheight', 'markerunits', 'markerwidth', 'orient', 'preserveaspectratio', 'refx', 'refy', 'viewbox', 'maskcontentunits', 'maskunits', 'd', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'fx', 'fy', 'offset', 'stop-color', 'stop-opacity', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'xml:space', 'method', 'spacing', 'startoffset', 'dx', 'dy', 'rotate', 'textlength', ]; /** * Allowed attributes in SVG file. * * Filters the list of allowed attributes in SVG files. * * Since SVG files can run JS code that may inject malicious code, all attributes * are removed except the allowed attributes. * * This hook can be used to manage allowed SVG attributes. To either add new * attributes or delete existing attributes. To strengthen or weaken site security. * * @param array $allowed_attributes A list of allowed attributes. */ $allowed_attributes = apply_filters( 'elementor/files/svg/allowed_attributes', $allowed_attributes ); return $allowed_attributes; } /** * Get Allowed Elements * * Returns an array of allowed element tags to be in SVG files. * * @since 3.16.0 * @access private * * @return array */ private function get_allowed_elements() { $allowed_elements = [ 'a', 'circle', 'clippath', 'defs', 'style', 'desc', 'ellipse', 'fegaussianblur', 'filter', 'foreignobject', 'g', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'svg', 'switch', 'symbol', 'text', 'textpath', 'title', 'tspan', 'use', ]; /** * Allowed elements in SVG file. * * Filters the list of allowed elements in SVG files. * * Since SVG files can run JS code that may inject malicious code, all elements * are removed except the allowed elements. * * This hook can be used to manage SVG elements. To either add new elements or * delete existing elements. To strengthen or weaken site security. * * @param array $allowed_elements A list of allowed elements. */ $allowed_elements = apply_filters( 'elementor/files/svg/allowed_elements', $allowed_elements ); return $allowed_elements; } /** * Validate Allowed Attributes * * @since 3.16.0 * @access private * * @param \DOMElement $element */ private function validate_allowed_attributes( $element ) { static $allowed_attributes = false; if ( false === $allowed_attributes ) { $allowed_attributes = $this->get_allowed_attributes(); } for ( $index = $element->attributes->length - 1; $index >= 0; $index-- ) { // get attribute name $attr_name = $element->attributes->item( $index )->name; $attr_name_lowercase = strtolower( $attr_name ); // Remove attribute if not in whitelist if ( ! in_array( $attr_name_lowercase, $allowed_attributes ) && ! $this->is_a_attribute( $attr_name_lowercase, 'aria' ) && ! $this->is_a_attribute( $attr_name_lowercase, 'data' ) ) { $element->removeAttribute( $attr_name ); continue; } $attr_value = $element->attributes->item( $index )->value; // Remove attribute if it has a remote reference or js or data-URI/base64 if ( ! empty( $attr_value ) && ( $this->is_remote_value( $attr_value ) || $this->has_js_value( $attr_value ) ) ) { $element->removeAttribute( $attr_name ); continue; } } } /** * Strip xlinks * * @since 3.16.0 * @access private * * @param \DOMElement $element */ private function strip_xlinks( $element ) { $xlinks = $element->getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); if ( ! $xlinks ) { return; } if ( ! $this->is_safe_href( $xlinks ) ) { $element->removeAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); } } /** * @see https://github.com/darylldoyle/svg-sanitizer/blob/2321a914e/src/Sanitizer.php#L454 */ private function is_safe_href( $value ) { // Allow empty values. if ( empty( $value ) ) { return true; } // Allow fragment identifiers. if ( '#' === substr( $value, 0, 1 ) ) { return true; } // Allow relative URIs. if ( '/' === substr( $value, 0, 1 ) ) { return true; } // Allow HTTPS domains. if ( 'https://' === substr( $value, 0, 8 ) ) { return true; } // Allow HTTP domains. if ( 'http://' === substr( $value, 0, 7 ) ) { return true; } // Allow known data URIs. if ( in_array( substr( $value, 0, 14 ), [ 'data:image/png', // PNG 'data:image/gif', // GIF 'data:image/jpg', // JPG 'data:image/jpe', // JPEG 'data:image/pjp', // PJPEG ], true ) ) { return true; } // Allow known short data URIs. if ( in_array( substr( $value, 0, 12 ), [ 'data:img/png', // PNG 'data:img/gif', // GIF 'data:img/jpg', // JPG 'data:img/jpe', // JPEG 'data:img/pjp', // PJPEG ], true ) ) { return true; } return false; } /** * Validate Use Tag * * @since 3.16.0 * @access private * * @param $element */ private function validate_use_tag( $element ) { $xlinks = $element->getAttributeNS( 'http://www.w3.org/1999/xlink', 'href' ); if ( $xlinks && '#' !== substr( $xlinks, 0, 1 ) ) { $element->parentNode->removeChild( $element ); // phpcs:ignore -- php DomNode } } /** * Strip Doctype * * @since 3.16.0 * @access private * */ private function strip_doctype() { foreach ( $this->svg_dom->childNodes as $child ) { if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType ) { // phpcs:ignore -- php DomDocument $child->parentNode->removeChild( $child ); // phpcs:ignore -- php DomDocument } } } /** * Sanitize Elements * * @since 3.16.0 * @access private */ private function sanitize_elements() { $elements = $this->svg_dom->getElementsByTagName( '*' ); // loop through all elements // we do this backwards so we don't skip anything if we delete a node // see comments at: http://php.net/manual/en/class.domnamednodemap.php for ( $index = $elements->length - 1; $index >= 0; $index-- ) { /** * @var \DOMElement $current_element */ $current_element = $elements->item( $index ); // If the tag isn't in the whitelist, remove it and continue with next iteration if ( ! $this->is_allowed_tag( $current_element ) ) { continue; } //validate element attributes $this->validate_allowed_attributes( $current_element ); $this->strip_xlinks( $current_element ); if ( 'use' === strtolower( $current_element->tagName ) ) { // phpcs:ignore -- php DomDocument $this->validate_use_tag( $current_element ); } } } /** * Strip PHP Tags * * @since 3.16.0 * @access private * * @param $string * @return string */ private function strip_php_tags( $string ) { $string = preg_replace( '/<\?(=|php)(.+?)\?>/i', '', $string ); // Remove XML, ASP, etc. $string = preg_replace( '/<\?(.*)\?>/Us', '', $string ); $string = preg_replace( '/<\%(.*)\%>/Us', '', $string ); if ( ( false !== strpos( $string, '/Us', '', $string ); $string = preg_replace( '/\/\*(.*)\*\//Us', '', $string ); if ( ( false !== strpos( $string, ' $generator $rss_info_name $rss_info_url $rss_info_description $pub_date $rss_info_language $wxr_version $wxr_site_url $rss_info_url $page_on_front_xml $dynamic EOT; return $result; } public function __construct( array $args = [] ) { global $wpdb; $this->args = wp_parse_args( $args, self::$default_args ); $this->wpdb = $wpdb; } } assets-translation-loader.php000064400000004774147207256750012412 0ustar00registered[ $handle ]->src; }, $handles ); } private static function default_replace_translation( $relative_path ) { // Translations are always based on the non-minified filename. $relative_path_without_ext = preg_replace( '/(\.min)?\.js$/i', '', $relative_path ); // By default, we suffix the file with `.strings` (e.g 'assets/js/editor.js' => 'assets/js/editor.strings.js'). return implode( '.', [ $relative_path_without_ext, 'strings', 'js', ] ); } } http.php000064400000001725147207256750006260 0ustar00request( $url, $args ); if ( $this->is_successful_response( $response ) ) { return $response; } } return $response; } /** * @param $response * * @return bool */ private function is_successful_response( $response ) { if ( is_wp_error( $response ) ) { return false; } $response_code = (int) wp_remote_retrieve_response_code( $response ); if ( in_array( $response_code, [ 0, 404, 500 ], true ) ) { return false; } return true; } } force-locale.php000064400000007070147207256750007633 0ustar00new_locale = $new_locale; $this->original_locale = $original_locale ? $original_locale : determine_locale(); $this->filter = function() use ( $new_locale ) { return $new_locale; }; } /** * Force the translations to use a specific locale. * * @return void */ public function force() { switch_to_locale( $this->new_locale ); /** * Reset the \WP_Textdomain_Registry instance to clear its cache. * * @see https://github.com/WordPress/wordpress-develop/blob/799d7dc86f5b07b17f7a418948fc851bd2fc334b/src/wp-includes/class-wp-textdomain-registry.php#L179-L187 * @see https://github.com/WordPress/wordpress-develop/blob/799d7dc86f5b07b17f7a418948fc851bd2fc334b/tests/phpunit/tests/l10n/wpLocaleSwitcher.php#L19-L31 */ $this->reset_textdomain_registry(); /** * Reset l10n in order to clear the translations cache. * * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L1324 * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L1222 * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L821 */ $this->reset_l10n(); /** * Force the translations of `$new_locale` to be loaded. * * @see https://github.com/WordPress/wordpress-develop/blob/2437ef5130f10153bc4fffa412d4f37e65e3d66b/src/wp-includes/l10n.php#L1294 */ add_filter( 'pre_determine_locale', $this->filter ); } /** * Restore the original locale and cleanup filters, etc. * * @return void */ public function restore() { $this->restore_textdomain_registry(); $this->reset_l10n(); switch_to_locale( $this->original_locale ); remove_filter( 'pre_determine_locale', $this->filter ); } private function reset_textdomain_registry() { if ( ! class_exists( '\WP_Textdomain_Registry' ) ) { return; } /** @var \WP_Textdomain_Registry $wp_textdomain_registry */ global $wp_textdomain_registry; $this->original_textdomain_registry = $wp_textdomain_registry; $wp_textdomain_registry = new \WP_Textdomain_Registry(); } private function restore_textdomain_registry() { if ( ! $this->original_textdomain_registry ) { return; } /** @var \WP_Textdomain_Registry $wp_textdomain_registry */ global $wp_textdomain_registry; $wp_textdomain_registry = $this->original_textdomain_registry; } /** * Reset the l10n global variables. * * @return void */ private function reset_l10n() { global $l10n, $l10n_unloaded; if ( is_array( $l10n ) ) { foreach ( $l10n as $domain => $l10n_data ) { unset( $l10n[ $domain ] ); } } if ( is_array( $l10n_unloaded ) ) { foreach ( $l10n_unloaded as $domain => $l10n_unloaded_data ) { unset( $l10n_unloaded[ $domain ] ); } } } } hints.php000064400000023266147207256750006432 0ustar00 [ self::DISMISSED => 'image-optimization-once', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], 'image-optimization-once-media-modal' => [ self::DISMISSED => 'image-optimization-once-media-modal', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], 'image-optimization' => [ self::DISMISSED => 'image_optimizer_hint', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], 'image-optimization-media-modal' => [ self::DISMISSED => 'image-optimization-media-modal', self::CAPABILITY => 'install_plugins', self::DEFINED => 'IMAGE_OPTIMIZATION_VERSION', ], ]; if ( ! $hint_key ) { return $hints; } return $hints[ $hint_key ] ?? []; } /** * get_notice_icon * @return string */ public static function get_notice_icon(): string { return '
'; } /** * get_notice_template * * Print or Retrieve the notice template. * @param array $notice * @param bool $return * * @return string|void */ public static function get_notice_template( array $notice, bool $return = false ) { $default_settings = [ 'type' => 'info', 'icon' => false, 'heading' => '', 'content' => '', 'dismissible' => false, 'button_text' => '', 'button_event' => '', 'button_data' => [], 'display' => false, ]; $notice_settings = array_merge( $default_settings, $notice ); if ( empty( $notice_settings['heading'] ) && empty( $notice_settings['content'] ) ) { return ''; } if ( ! in_array( $notice_settings['type'], self::get_notice_types(), true ) ) { $notice_settings['type'] = 'info'; } $icon = ''; $heading = ''; $content = ''; $dismissible = ''; $button = ''; if ( $notice_settings['icon'] ) { $icon = self::get_notice_icon(); } if ( ! empty( $notice_settings['heading'] ) ) { $heading = '
' . $notice_settings['heading'] . '
'; } if ( ! empty( $notice_settings['content'] ) ) { $content = '
' . $notice_settings['content'] . '
'; } if ( ! empty( $notice_settings['button_text'] ) ) { $button_settings = ( ! empty( $notice_settings['button_data'] ) ) ? ' data-settings="' . esc_attr( json_encode( $notice_settings['button_data'] ) ) . '"' : ''; $button = '
'; } if ( $notice_settings['dismissible'] ) { $dismissible = ''; } $notice_template = sprintf( '
%2$s
%3$s %4$s %5$s
%6$s
', $notice_settings['type'], $icon, $heading, $content, $button, $dismissible, $notice_settings['display'] ); if ( $return ) { return $notice_template; } echo wp_kses( $notice_template, self::get_notice_allowed_html() ); } /** * get_plugin_install_url * @param $plugin_slug * * @return string */ public static function get_plugin_install_url( $plugin_slug ): string { $action = 'install-plugin'; return wp_nonce_url( add_query_arg( [ 'action' => $action, 'plugin' => $plugin_slug, ], admin_url( 'update.php' ) ), $action . '_' . $plugin_slug ); } /** * get_plugin_activate_url * @param $plugin_slug * * @return string */ public static function get_plugin_activate_url( $plugin_slug ): string { $path = "$plugin_slug/$plugin_slug.php"; return wp_nonce_url( admin_url( 'plugins.php?action=activate&plugin=' . $path ), 'activate-plugin_' . $path ); } /** * is_dismissed * @param $key * * @return bool */ public static function is_dismissed( $key ): bool { $dismissed = User::get_dismissed_editor_notices(); return in_array( $key, $dismissed, true ); } /** * should_display_hint * @param $hint_key * * @return bool */ public static function should_display_hint( $hint_key ): bool { $hint = self::get_hints( $hint_key ); if ( empty( $hint ) ) { return false; } foreach ( $hint as $key => $value ) { switch ( $key ) { case self::DISMISSED: if ( self::is_dismissed( $value ) ) { return false; } break; case self::CAPABILITY: if ( ! current_user_can( $value ) ) { return false; } break; case self::DEFINED: if ( defined( $value ) ) { return false; } break; case self::PLUGIN_INSTALLED: if ( ! self::is_plugin_installed( $value ) ) { return false; } break; case self::PLUGIN_ACTIVE: if ( ! self::is_plugin_active( $value ) ) { return false; } break; } } return true; } private static function is_conflict_plugin_installed(): bool { if ( ! Utils::has_pro() ) { return false; } $conflicting_plugins = [ 'imagify/imagify.php', 'optimole-wp/optimole-wp.php', 'ewww-image-optimizer/ewww-image-optimizer.php', 'ewww-image-optimizer-cloud/ewww-image-optimizer-cloud.php', 'kraken-image-optimizer/kraken.php', 'shortpixel-image-optimiser/wp-shortpixel.php', 'wp-smushit/wp-smush.php', 'wp-smush-pro/wp-smush.php', 'tiny-compress-images/tiny-compress-images.php', ]; foreach ( $conflicting_plugins as $plugin ) { if ( self::is_plugin_active( $plugin ) ) { return true; } } return false; } /** * is_plugin_installed * @param $plugin * * @return bool */ public static function is_plugin_installed( $plugin ) : bool { $plugins = get_plugins(); $plugin = self::ensure_plugin_folder( $plugin ); return ! empty( $plugins[ $plugin ] ); } /** * is_plugin_active * @param $plugin * * @return bool */ public static function is_plugin_active( $plugin ): bool { $plugin = self::ensure_plugin_folder( $plugin ); return is_plugin_active( $plugin ); } /** * get_plugin_action_url * @param $plugin * * @return string */ public static function get_plugin_action_url( $plugin ): string { if ( ! self::is_plugin_installed( $plugin ) ) { return self::get_plugin_install_url( $plugin ); } if ( ! self::is_plugin_active( $plugin ) ) { return self::get_plugin_activate_url( $plugin ); } return ''; } /** * ensure_plugin_folder * @param $plugin * * @return string */ private static function ensure_plugin_folder( $plugin ): string { if ( false === strpos( $plugin, '/' ) ) { $plugin = $plugin . '/' . $plugin . '.php'; } return $plugin; } /** * get_notice_allowed_html * @return array[] */ public static function get_notice_allowed_html(): array { return [ 'div' => [ 'class' => [], 'data-display' => [], ], 'svg' => [ 'width' => [], 'height' => [], 'viewbox' => [], 'fill' => [], 'xmlns' => [], ], 'path' => [ 'd' => [], 'stroke' => [], 'stroke-width' => [], 'stroke-linecap' => [], 'stroke-linejoin' => [], ], 'button' => [ 'class' => [], 'data-event' => [], 'data-settings' => [], 'data-tooltip' => [], ], 'i' => [ 'class' => [], 'aria-hidden' => [], ], 'span' => [ 'class' => [], ], 'a' => [ 'href' => [], 'style' => [], 'target' => [], ], ]; } } promotions/filtered-promotions-manager.php000064400000004143147207256750015124 0ustar00path_resolver = $path_resolver; return $this; } /** * Load asset config from a file into the collection. * * @param $key * @param $path * * @return $this */ public function load( $key, $path = null ) { if ( ! $path && $this->path_resolver ) { $path_resolver_callback = $this->path_resolver; $path = $path_resolver_callback( $key ); } if ( ! $path || ! file_exists( $path ) ) { return $this; } $config = require $path; if ( ! $this->is_valid_handle( $config ) ) { return $this; } $this->items[ $key ] = [ 'handle' => $config['handle'], 'deps' => $this->is_valid_deps( $config ) ? $config['deps'] : [], ]; return $this; } /** * Check that the handle property in the config is a valid. * * @param $config * * @return bool */ private function is_valid_handle( $config ) { return ! empty( $config['handle'] ) && is_string( $config['handle'] ); } /** * Check that the deps property in the config is a valid. * * @param $config * * @return bool */ private function is_valid_deps( $config ) { return isset( $config['deps'] ) && is_array( $config['deps'] ); } } collection.php000064400000022573147207256750007440 0ustar00items = $items; } /** * @param array $items * * @return static */ public static function make( array $items = [] ) { return new static( $items ); } /** * @param callable|null $callback * * @return $this */ public function filter( callable $callback = null ) { if ( ! $callback ) { return new static( array_filter( $this->items ) ); } return new static( array_filter( $this->items, $callback, ARRAY_FILTER_USE_BOTH ) ); } /** * @param $items * * @return $this */ public function merge( $items ) { if ( $items instanceof Collection ) { $items = $items->all(); } return new static( array_merge( $this->items, $items ) ); } /** * Union the collection with the given items. * * @param array $items * * @return $this */ public function union( array $items ) { return new static( $this->all() + $items ); } /** * Merge array recursively * * @param $items * * @return $this */ public function merge_recursive( $items ) { if ( $items instanceof Collection ) { $items = $items->all(); } return new static( array_merge_recursive( $this->items, $items ) ); } /** * Replace array recursively * * @param $items * * @return $this */ public function replace_recursive( $items ) { if ( $items instanceof Collection ) { $items = $items->all(); } return new static( array_replace_recursive( $this->items, $items ) ); } /** * Implode the items * * @param $glue * * @return string */ public function implode( $glue ) { return implode( $glue, $this->items ); } /** * Run a map over each of the items. * * @param callable $callback * @return $this */ public function map( callable $callback ) { $keys = array_keys( $this->items ); $items = array_map( $callback, $this->items, $keys ); return new static( array_combine( $keys, $items ) ); } /** * Run a callback over each of the items. * * @param callable $callback * @return $this */ public function each( callable $callback ) { foreach ( $this->items as $key => $value ) { if ( false === $callback( $value, $key ) ) { break; } } return $this; } /** * @param callable $callback * @param null $initial * * @return mixed|null */ public function reduce( callable $callback, $initial = null ) { $result = $initial; foreach ( $this->all() as $key => $value ) { $result = $callback( $result, $value, $key ); } return $result; } /** * @param callable $callback * * @return $this */ public function map_with_keys( callable $callback ) { $result = []; foreach ( $this->items as $key => $value ) { $assoc = $callback( $value, $key ); foreach ( $assoc as $map_key => $map_value ) { $result[ $map_key ] = $map_value; } } return new static( $result ); } /** * Get all items except for those with the specified keys. * * @param array $keys * * @return $this */ public function except( array $keys ) { return $this->filter( function ( $value, $key ) use ( $keys ) { return ! in_array( $key, $keys, true ); } ); } /** * Get the items with the specified keys. * * @param array $keys * * @return $this */ public function only( array $keys ) { return $this->filter( function ( $value, $key ) use ( $keys ) { return in_array( $key, $keys, true ); } ); } /** * Run over the collection to get specific prop from the collection item. * * @param $key * * @return $this */ public function pluck( $key ) { $result = []; foreach ( $this->items as $item ) { $result[] = $this->get_item_value( $item, $key ); } return new static( $result ); } /** * Group the collection items by specific key in each collection item. * * @param $group_by * * @return $this */ public function group_by( $group_by ) { $result = []; foreach ( $this->items as $item ) { $group_key = $this->get_item_value( $item, $group_by, 0 ); $result[ $group_key ][] = $item; } return new static( $result ); } /** * Sort keys * * @param false $descending * * @return $this */ public function sort_keys( $descending = false ) { $items = $this->items; if ( $descending ) { krsort( $items ); } else { ksort( $items ); } return new static( $items ); } /** * Get specific item from the collection. * * @param $key * @param null $default * * @return mixed|null */ public function get( $key, $default = null ) { if ( ! array_key_exists( $key, $this->items ) ) { return $default; } return $this->items[ $key ]; } /** * Get the first item. * * @param null $default * * @return mixed|null */ public function first( $default = null ) { if ( $this->is_empty() ) { return $default; } foreach ( $this->items as $item ) { return $item; } } /** * Find an element from the items. * * @param callable $callback * @param null $default * * @return mixed|null */ public function find( callable $callback, $default = null ) { foreach ( $this->all() as $key => $item ) { if ( $callback( $item, $key ) ) { return $item; } } return $default; } /** * @param callable|string|int $value * * @return bool */ public function contains( $value ) { $callback = $value instanceof \Closure ? $value : function ( $item ) use ( $value ) { return $item === $value; }; foreach ( $this->all() as $key => $item ) { if ( $callback( $item, $key ) ) { return true; } } return false; } /** * Make sure all the values inside the array are uniques. * * @param null|string|string[] $keys * * @return $this */ public function unique( $keys = null ) { if ( ! $keys ) { return new static( array_unique( $this->items ) ); } if ( ! is_array( $keys ) ) { $keys = [ $keys ]; } $exists = []; return $this->filter( function ( $item ) use ( $keys, &$exists ) { $value = null; foreach ( $keys as $key ) { $current_value = $this->get_item_value( $item, $key ); $value .= "{$key}:{$current_value};"; } // If no value for the specific key return the item. if ( null === $value ) { return true; } // If value is not exists, add to the exists array and return the item. if ( ! in_array( $value, $exists, true ) ) { $exists[] = $value; return true; } return false; } ); } /** * @return array */ public function keys() { return array_keys( $this->items ); } /** * @return bool */ public function is_empty() { return empty( $this->items ); } /** * @return array */ public function all() { return $this->items; } /** * @return array */ public function values() { return array_values( $this->all() ); } /** * Support only one level depth. * * @return $this */ public function flatten() { $result = []; foreach ( $this->all() as $item ) { $item = $item instanceof Collection ? $item->all() : $item; if ( ! is_array( $item ) ) { $result[] = $item; } else { $values = array_values( $item ); foreach ( $values as $value ) { $result[] = $value; } } } return new static( $result ); } /** * @param ...$values * * @return $this */ public function push( ...$values ) { foreach ( $values as $value ) { $this->items[] = $value; } return $this; } public function prepend( ...$values ) { $this->items = array_merge( $values, $this->items ); return $this; } public function some( callable $callback ) { foreach ( $this->items as $key => $item ) { if ( $callback( $item, $key ) ) { return true; } } return false; } /** * @param mixed $offset * * @return bool */ #[\ReturnTypeWillChange] public function offsetExists( $offset ) { return isset( $this->items[ $offset ] ); } /** * @param mixed $offset * * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet( $offset ) { return $this->items[ $offset ]; } /** * @param mixed $offset * @param mixed $value */ #[\ReturnTypeWillChange] public function offsetSet( $offset, $value ) { if ( is_null( $offset ) ) { $this->items[] = $value; } else { $this->items[ $offset ] = $value; } } /** * @param mixed $offset */ #[\ReturnTypeWillChange] public function offsetUnset( $offset ) { unset( $this->items[ $offset ] ); } /** * @return \ArrayIterator|\Traversable */ #[\ReturnTypeWillChange] public function getIterator() { return new \ArrayIterator( $this->items ); } /** * @return int|void */ #[\ReturnTypeWillChange] public function count() { return count( $this->items ); } /** * @param $item * @param $key * @param null $default * * @return mixed|null */ private function get_item_value( $item, $key, $default = null ) { $value = $default; if ( is_object( $item ) && isset( $item->{$key} ) ) { $value = $item->{$key}; } elseif ( is_array( $item ) && isset( $item[ $key ] ) ) { $value = $item[ $key ]; } return $value; } } plugins-manager.php000064400000005532147207256750010372 0ustar00upgrader = $upgrader; } else { $skin = new WP_Ajax_Upgrader_Skin(); $this->upgrader = new Plugin_Upgrader( $skin ); } } /** * Install plugin or an array of plugins. * * @since 3.6.2 * * @param string|array $plugins * @return array [ 'succeeded' => [] , 'failed' => [] ] */ public function install( $plugins ) { $succeeded = []; $failed = []; $already_installed_plugins = Plugin::$instance->wp->get_plugins(); if ( ! is_array( $plugins ) ) { $plugins = [ $plugins ]; } foreach ( $plugins as $plugin ) { if ( in_array( $plugin, $already_installed_plugins->keys(), true ) ) { $succeeded[] = $plugin; continue; } $slug = $this->clean_slug( $plugin ); $api = Plugin::$instance->wp->plugins_api('plugin_information', [ 'slug' => $slug, 'fields' => array( 'short_description' => false, 'sections' => false, 'requires' => false, 'rating' => false, 'ratings' => false, 'downloaded' => false, 'last_updated' => false, 'added' => false, 'tags' => false, 'compatibility' => false, 'homepage' => false, 'donate_link' => false, ), ] ); if ( ! isset( $api->download_link ) ) { $failed[] = $plugin; continue; } $installation = $this->upgrader->install( $api->download_link ); if ( $installation ) { $succeeded[] = $plugin; } else { $failed[] = $plugin; } } return [ 'succeeded' => $succeeded, 'failed' => $failed, ]; } /** * Activate plugin or array off plugins. * * @since 3.6.2 * * @param array|string $plugins * @return array [ 'succeeded' => [] , 'failed' => [] ] */ public function activate( $plugins ) { $succeeded = []; $failed = []; if ( ! is_array( $plugins ) ) { $plugins = [ $plugins ]; } foreach ( $plugins as $plugin ) { if ( Plugin::$instance->wp->is_plugin_active( $plugin ) ) { $succeeded[] = $plugin; continue; } Plugin::$instance->wp->activate_plugin( $plugin ); if ( Plugin::$instance->wp->is_plugin_active( $plugin ) ) { $succeeded[] = $plugin; } else { $failed[] = $plugin; } } return [ 'succeeded' => $succeeded, 'failed' => $failed, ]; } private function clean_slug( $initial_slug ) { return explode( '/', $initial_slug )[0]; } } version.php000064400000007211147207256750006762 0ustar00major1 = $major1; $this->major2 = $major2; $this->patch = $patch; $this->stage = $stage; } /** * Create Version instance. * * @param string $major1 * @param string $major2 * @param string $patch * @param null $stage * * @return static */ public static function create( $major1 = '0', $major2 = '0', $patch = '0', $stage = null ) { return new static( $major1, $major2, $patch, $stage ); } /** * Checks if the current version string is valid. * * @param $version * * @return bool */ public static function is_valid_version( $version ) { return ! ! preg_match( '/^(\d+\.)?(\d+\.)?(\*|\d+)(-.+)?$/', $version ); } /** * Creates a Version instance from a string. * * @param $version * @param bool $should_validate * * @return static * @throws \Exception */ public static function create_from_string( $version, $should_validate = true ) { if ( $should_validate && ! static::is_valid_version( $version ) ) { throw new \Exception( "{$version} is an invalid version." ); } $parts = explode( '.', $version ); $patch_parts = []; $major1 = '0'; $major2 = '0'; $patch = '0'; $stage = null; if ( isset( $parts[0] ) ) { $major1 = $parts[0]; } if ( isset( $parts[1] ) ) { $major2 = $parts[1]; } if ( isset( $parts[2] ) ) { $patch_parts = explode( '-', $parts[2] ); $patch = $patch_parts[0]; } if ( isset( $patch_parts[1] ) ) { $stage = $patch_parts[1]; } return static::create( $major1, $major2, $patch, $stage ); } /** * Compare the current version instance with another version. * * @param $operator * @param $version * @param string $part * * @return bool * @throws \Exception */ public function compare( $operator, $version, $part = self::PART_STAGE ) { if ( ! ( $version instanceof Version ) ) { if ( ! static::is_valid_version( $version ) ) { $version = '0.0.0'; } $version = static::create_from_string( $version, false ); } $current_version = clone $this; $compare_version = clone $version; if ( in_array( $part, [ self::PART_PATCH, self::PART_MAJOR_2, self::PART_MAJOR_1 ], true ) ) { $current_version->stage = null; $compare_version->stage = null; } if ( in_array( $part, [ self::PART_MAJOR_2, self::PART_MAJOR_1 ], true ) ) { $current_version->patch = '0'; $compare_version->patch = '0'; } if ( self::PART_MAJOR_1 === $part ) { $current_version->major2 = '0'; $compare_version->major2 = '0'; } return version_compare( $current_version, $compare_version, $operator ); } /** * Implode the version and return it as string. * * @return string */ public function __toString() { $version = implode( '.', [ $this->major1, $this->major2, $this->patch ] ); if ( $this->stage ) { $version .= '-' . $this->stage; } return $version; } }