+ $.each(attributes, function() {
+ if(this.name) {
+ attributes_html += ' ' + this.name + '="' + this.value + '"';
+ }
+ });
+ $inputElement.replaceWith($('
'));
+ $inputElement = $('[data-richtext="init"]');
+ $inputElement.removeAttr("data-richtext");
+ }
+
+ $editor = $('
', {class: "richText"});
+ var $toolbar = $('
', {class: "richText-toolbar"});
+ //var $editorView = $('
', {class: "richText-editor", id: editorID, contenteditable: true, name: settings.id});
+ var $editorView = $('
', {class: "richText-editor", id: editorID, contenteditable: true});
+ $toolbar.append($toolbarList);
+
+ $toolbarList.append($toolbarElement.clone().append($btnUndo));
+ $toolbarList.append($toolbarElement.clone().append($btnRedo));
+
+ /* text formatting */
+ if(settings.bold === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnBold));
+ }
+ if(settings.italic === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnItalic));
+ }
+ if(settings.underline === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnUnderline));
+ }
+
+ /* align */
+ if(settings.leftAlign === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnLeftAlign));
+ }
+ if(settings.centerAlign === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnCenterAlign));
+ }
+ if(settings.rightAlign === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnRightAlign));
+ }
+ if(settings.justify === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnJustify));
+ }
+
+ /* lists */
+ if(settings.ol === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnOL));
+ }
+ if(settings.ul === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnUL));
+ }
+
+ /* fonts */
+ if(settings.fonts === true && settings.fontList.length > 0) {
+ $toolbarList.append($toolbarElement.clone().append($btnFont));
+ }
+ if(settings.fontSize === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnFontSize));
+ }
+
+ /* heading */
+ if(settings.heading === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnHeading));
+ }
+
+ /* colors */
+ if(settings.fontColor === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnFontColor));
+ }
+
+ /* uploads */
+ if(settings.imageUpload === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnImageUpload));
+ }
+ if(settings.fileUpload === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnFileUpload));
+ }
+
+ /* media */
+ if(settings.videoEmbed === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnVideoEmbed));
+ }
+
+ /* urls */
+ if(settings.urls === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnURLs));
+ }
+
+ if(settings.table === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnTable));
+ }
+
+ /* code */
+ if(settings.removeStyles === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnRemoveStyles));
+ }
+ if(settings.code === true) {
+ $toolbarList.append($toolbarElement.clone().append($btnCode));
+ }
+
+ // set current textarea value to editor
+ $editorView.html($inputElement.val());
+
+ $editor.append($toolbar);
+ $editor.append($editorView);
+ $editor.append($inputElement.clone().hide());
+ $inputElement.replaceWith($editor);
+
+ // append bottom toolbar
+ /*$editor.append(
+ $('
', {class: 'richText-toolbar'})
+ .append($('
', {class: 'richText-undo is-disabled', html: '
', 'title': settings.translations.undo}))
+ .append($('
', {class: 'richText-redo is-disabled', html: '
', 'title': settings.translations.redo}))
+ .append($('
', {class: 'richText-help', html: '
'}))
+ );*/
+
+ if(settings.height && settings.height > 0) {
+ // set custom editor height
+ $editor.children(".richText-editor, .richText-initial").css({'min-height' : settings.height + 'px', 'height' : settings.height + 'px'});
+ } else if(settings.heightPercentage && settings.heightPercentage > 0) {
+ // set custom editor height in percentage
+ var parentHeight = $editor.parent().innerHeight(); // get editor parent height
+ var height = (settings.heightPercentage/100) * parentHeight; // calculate pixel value from percentage
+ height -= $toolbar.outerHeight()*2; // remove toolbar size
+ height -= parseInt($editor.css("margin-top")); // remove margins
+ height -= parseInt($editor.css("margin-bottom")); // remove margins
+ height -= parseInt($editor.find(".richText-editor").css("padding-top")); // remove paddings
+ height -= parseInt($editor.find(".richText-editor").css("padding-bottom")); // remove paddings
+ $editor.children(".richText-editor, .richText-initial").css({'min-height' : height + 'px', 'height' : height + 'px'});
+ }
+
+ // add custom class
+ if(settings.class) {
+ $editor.addClass(settings.class);
+ }
+ if(settings.id) {
+ $editor.attr("id", settings.id);
+ }
+
+ // fix the first line
+ fixFirstLine();
+
+ // save history
+ history[editorID].push($editor.find("textarea").val());
+ }
+
+ // initialize editor
+ init();
+
+
+ /** EVENT HANDLERS */
+
+ // Help popup
+ $editor.find(".richText-help").on("click", function() {
+ var $editor = $(this).parents(".richText");
+ if($editor) {
+ var $outer = $('
', {class: 'richText-help-popup', style: 'position:absolute;top:0;right:0;bottom:0;left:0;background-color: rgba(0,0,0,0.3);'});
+ var $inner = $('
', {style: 'position:relative;margin:60px auto;padding:20px;background-color:#FAFAFA;width:70%;font-family:Calibri,Verdana,Helvetica,sans-serif;font-size:small;'});
+ var $content = $('
', {html: '
'});
+ $content.append('
RichText ');
+ $content.append('
Powered by
webfashionist/RichText (Github)
License:
AGPL-3.0 ');
+
+ $outer.append($inner.append($content));
+ $editor.append($outer);
+
+ $outer.on("click", "#closeHelp", function() {
+ $(this).parents('.richText-help-popup').remove();
+ });
+ }
+ });
+
+ // undo / redo
+ $(document).on("click", ".richText-undo, .richText-redo", function(e) {
+ var $this = $(this);
+ var $editor = $this.parents('.richText');
+ if($this.hasClass("richText-undo") && !$this.hasClass("is-disabled")) {
+ undo($editor);
+ } else if($this.hasClass("richText-redo") && !$this.hasClass("is-disabled")) {
+ redo($editor);
+ }
+ });
+
+
+ // Saving changes from editor to textarea
+ $(document).on("input change blur keydown keyup", ".richText-editor", function(e) {
+ if((e.keyCode === 9 || e.keyCode === "9") && e.type === "keydown") {
+ // tab through table cells
+ e.preventDefault();
+ tabifyEditableTable(window, e);
+ return false;
+ }
+ fixFirstLine();
+ updateTextarea();
+ doSave($(this).attr("id"));
+ });
+
+
+ // add context menu to several Node elements
+ $(document).on('contextmenu', '.richText-editor', function(e) {
+
+ var $list = $('
', {'class': 'list-rightclick richText-list'});
+ var $li = $('
');
+ // remove Node selection
+ $('.richText-editor').find('.richText-editNode').removeClass('richText-editNode');
+
+ var $target = $(e.target);
+ var $richText = $target.parents('.richText');
+ var $toolbar = $richText.find('.richText-toolbar');
+
+ var positionX = e.pageX - $richText.offset().left;
+ var positionY = e.pageY - $richText.offset().top;
+
+ $list.css({
+ 'top': positionY,
+ 'left': positionX
+ });
+
+
+ if($target.prop("tagName") === "A") {
+ // edit URL
+ e.preventDefault();
+
+ $list.append($li.clone().html('
'));
+ $target.parents('.richText').append($list);
+ $list.find('.fa-link').on('click', function() {
+ $('.list-rightclick.richText-list').remove();
+ $target.addClass('richText-editNode');
+ var $popup = $toolbar.find('#richText-URL');
+ $popup.find('input#url').val($target.attr('href'));
+ $popup.find('input#urlText').val($target.text());
+ $popup.find('select#openIn').val($target.attr('target'));
+ $toolbar.find('.richText-btn').children('.fa-link').parents('li').addClass('is-selected');
+ });
+
+ return false;
+ } else if($target.prop("tagName") === "IMG") {
+ // edit image
+ e.preventDefault();
+
+ $list.append($li.clone().html('
'));
+ $target.parents('.richText').append($list);
+ $list.find('.fa-image').on('click', function() {
+ var align;
+ if($target.parent('div').length > 0 && $target.parent('div').attr('style') === 'text-align:center;') {
+ align = 'center';
+ } else {
+ align = $target.attr('align');
+ }
+ $('.list-rightclick.richText-list').remove();
+ $target.addClass('richText-editNode');
+ var $popup = $toolbar.find('#richText-Image');
+ $popup.find('input#imageURL').val($target.attr('src'));
+ $popup.find('select#align').val(align);
+ $toolbar.find('.richText-btn').children('.fa-image').parents('li').addClass('is-selected');
+ });
+
+ return false;
+ }
+
+ });
+
+ // Saving changes from textarea to editor
+ $(document).on("input change blur", ".richText-initial", function() {
+ if(settings.useSingleQuotes === true) {
+ $(this).val(changeAttributeQuotes($(this).val()));
+ }
+ var editorID = $(this).siblings('.richText-editor').attr("id");
+ updateEditor(editorID);
+ doSave(editorID);
+ });
+
+ // Save selection seperately (mainly needed for Safari)
+ $(document).on("dblclick mouseup", ".richText-editor", function() {
+ var editorID = $(this).attr("id");
+ doSave(editorID);
+ });
+
+ // embedding video
+ $(document).on("click", "#richText-Video button.btn", function(event) {
+ event.preventDefault();
+ var $button = $(this);
+ var $form = $button.parent('.richText-form-item').parent('.richText-form');
+ if($form.attr("data-editor") === editorID) {
+ // only for the currently selected editor
+ var url = $form.find('input#videoURL').val();
+ var size = $form.find('select#size').val();
+
+ if(!url) {
+ // no url set
+ $form.prepend($('
', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseEnterURL}));
+ $form.children('.form-item.is-error').slideDown();
+ setTimeout(function() {
+ $form.children('.form-item.is-error').slideUp(function () {
+ $(this).remove();
+ });
+ }, 5000);
+ } else {
+ // write html in editor
+ var html = '';
+ html = getVideoCode(url, size);
+ if(!html) {
+ $form.prepend($('
', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.videoURLnotSupported}));
+ $form.children('.form-item.is-error').slideDown();
+ setTimeout(function() {
+ $form.children('.form-item.is-error').slideUp(function () {
+ $(this).remove();
+ });
+ }, 5000);
+ } else {
+ if(settings.useSingleQuotes === true) {
+
+ } else {
+
+ }
+ restoreSelection(editorID, true);
+ pasteHTMLAtCaret(html);
+ updateTextarea();
+ // reset input values
+ $form.find('input#videoURL').val('');
+ $('.richText-toolbar li.is-selected').removeClass("is-selected");
+ }
+ }
+ }
+ });
+
+ // Resize images
+ $(document).on('mousedown', function(e) {
+ var $target = $(e.target);
+ if(!$target.hasClass('richText-list') && $target.parents('.richText-list').length === 0) {
+ // remove context menu
+ $('.richText-list.list-rightclick').remove();
+ if(!$target.hasClass('richText-form') && $target.parents('.richText-form').length === 0) {
+ $('.richText-editNode').each(function () {
+ var $this = $(this);
+ $this.removeClass('richText-editNode');
+ if ($this.attr('class') === '') {
+ $this.removeAttr('class');
+ }
+ });
+ }
+ }
+ if($target.prop("tagName") === "IMG" && $target.parents("#" + editorID)) {
+ startX = e.pageX;
+ startY = e.pageY;
+ startW = $target.innerWidth();
+ startH = $target.innerHeight();
+
+ var left = $target.offset().left;
+ var right = $target.offset().left + $target.innerWidth();
+ var bottom = $target.offset().top + $target.innerHeight();
+ var top = $target.offset().top;
+ var resize = false;
+ $target.css({'cursor' : 'default'});
+
+ if(startY <= bottom && startY >= bottom-20 && startX >= right-20 && startX <= right) {
+ // bottom right corner
+ $resizeImage = $target;
+ $resizeImage.css({'cursor' : 'nwse-resize'});
+ resize = true;
+ }
+
+ if((resize === true || $resizeImage) && !$resizeImage.data("width")) {
+ // set initial image size and prevent dragging image while resizing
+ $resizeImage.data("width", $target.parents("#" + editorID).innerWidth());
+ $resizeImage.data("height", $target.parents("#" + editorID).innerHeight()*3);
+ e.preventDefault();
+ } else if(resize === true || $resizeImage) {
+ // resizing active, prevent other events
+ e.preventDefault();
+ } else {
+ // resizing disabled, allow dragging image
+ $resizeImage = null;
+ }
+
+ }
+ });
+ $(document)
+ .mouseup(function(){
+ if($resizeImage) {
+ $resizeImage.css({'cursor' : 'default'});
+ }
+ $resizeImage = null;
+ })
+ .mousemove(function(e){
+ if($resizeImage!==null){
+ var maxWidth = $resizeImage.data('width');
+ var currentWidth = $resizeImage.width();
+ var maxHeight = $resizeImage.data('height');
+ var currentHeight = $resizeImage.height();
+ if((startW + e.pageX-startX) <= maxWidth && (startH + e.pageY-startY) <= maxHeight) {
+ // only resize if new size is smaller than the original image size
+ $resizeImage.innerWidth (startW + e.pageX-startX); // only resize width to adapt height proportionally
+ // $box.innerHeight(startH + e.pageY-startY);
+ updateTextarea();
+ } else if((startW + e.pageX-startX) <= currentWidth && (startH + e.pageY-startY) <= currentHeight) {
+ // only resize if new size is smaller than the previous size
+ $resizeImage.innerWidth (startW + e.pageX-startX); // only resize width to adapt height proportionally
+ updateTextarea();
+ }
+ }
+ });
+
+ // adding URL
+ $(document).on("click", "#richText-URL button.btn", function(event) {
+ event.preventDefault();
+ var $button = $(this);
+ var $form = $button.parent('.richText-form-item').parent('.richText-form');
+ if($form.attr("data-editor") === editorID) {
+ // only for currently selected editor
+ var url = $form.find('input#url').val();
+ var text = $form.find('input#urlText').val();
+ var target = $form.find('#openIn').val();
+
+ // set default values
+ if(!target) {
+ target = '_self';
+ }
+ if(!text) {
+ text = url;
+ }
+ if(!url) {
+ // no url set
+ $form.prepend($('
', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseEnterURL}));
+ $form.children('.form-item.is-error').slideDown();
+ setTimeout(function() {
+ $form.children('.form-item.is-error').slideUp(function () {
+ $(this).remove();
+ });
+ }, 5000);
+ } else {
+ // write html in editor
+ var html = '';
+ if(settings.useSingleQuotes === true) {
+ html = "
" + text + " ";
+ } else {
+ html = '
' + text + ' ';
+ }
+ restoreSelection(editorID, false, true);
+
+ var $editNode = $('.richText-editNode');
+ if($editNode.length > 0 && $editNode.prop("tagName") === "A") {
+ $editNode.attr("href", url);
+ $editNode.attr("target", target);
+ $editNode.text(text);
+ $editNode.removeClass('richText-editNode');
+ if($editNode.attr('class') === '') {
+ $editNode.removeAttr('class');
+ }
+ } else {
+ pasteHTMLAtCaret(html);
+ }
+ // reset input values
+ $form.find('input#url').val('');
+ $form.find('input#urlText').val('');
+ $('.richText-toolbar li.is-selected').removeClass("is-selected");
+ }
+ }
+ });
+
+ // adding image
+ $(document).on("click", "#richText-Image button.btn", function(event) {
+ event.preventDefault();
+ var $button = $(this);
+ var $form = $button.parent('.richText-form-item').parent('.richText-form');
+ if($form.attr("data-editor") === editorID) {
+ // only for currently selected editor
+ var url = $form.find('#imageURL').val();
+ var align = $form.find('select#align').val();
+
+ // set default values
+ if(!align) {
+ align = 'center';
+ }
+ if(!url) {
+ // no url set
+ $form.prepend($('
', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseSelectImage}));
+ $form.children('.form-item.is-error').slideDown();
+ setTimeout(function() {
+ $form.children('.form-item.is-error').slideUp(function () {
+ $(this).remove();
+ });
+ }, 5000);
+ } else {
+ // write html in editor
+ var html = '';
+ if(settings.useSingleQuotes === true) {
+ if(align === "center") {
+ html = "
";
+ } else {
+ html = "
";
+ }
+ } else {
+ if(align === "center") {
+ html = '
';
+ } else {
+ html = '
';
+ }
+ }
+ restoreSelection(editorID, true);
+ var $editNode = $('.richText-editNode');
+ if($editNode.length > 0 && $editNode.prop("tagName") === "IMG") {
+ $editNode.attr("src", url);
+ if($editNode.parent('div').length > 0 && $editNode.parent('div').attr('style') === 'text-align:center;' && align !== 'center') {
+ $editNode.unwrap('div');
+ $editNode.attr('align', align);
+ } else if(($editNode.parent('div').length === 0 || $editNode.parent('div').attr('style') !== 'text-align:center;') && align === 'center' ) {
+ $editNode.wrap('
');
+ $editNode.removeAttr('align');
+ } else {
+ $editNode.attr('align', align);
+ }
+ $editNode.removeClass('richText-editNode');
+ if($editNode.attr('class') === '') {
+ $editNode.removeAttr('class');
+ }
+ } else {
+ pasteHTMLAtCaret(html);
+ }
+ // reset input values
+ $form.find('input#imageURL').val('');
+ $('.richText-toolbar li.is-selected').removeClass("is-selected");
+ }
+ }
+ });
+
+ // adding file
+ $(document).on("click", "#richText-File button.btn", function(event) {
+ event.preventDefault();
+ var $button = $(this);
+ var $form = $button.parent('.richText-form-item').parent('.richText-form');
+ if($form.attr("data-editor") === editorID) {
+ // only for currently selected editor
+ var url = $form.find('#fileURL').val();
+ var text = $form.find('#fileText').val();
+
+ // set default values
+ if(!text) {
+ text = url;
+ }
+ if(!url) {
+ // no url set
+ $form.prepend($('
', {style: 'color:red;display:none;', class: 'form-item is-error', text: settings.translations.pleaseSelectFile}));
+ $form.children('.form-item.is-error').slideDown();
+ setTimeout(function() {
+ $form.children('.form-item.is-error').slideUp(function () {
+ $(this).remove();
+ });
+ }, 5000);
+ } else {
+ // write html in editor
+ var html = '';
+ if(settings.useSingleQuotes === true) {
+ html = "
" + text + " ";
+ } else {
+ html = '
' + text + ' ';
+ }
+ restoreSelection(editorID, true);
+ pasteHTMLAtCaret(html);
+ // reset input values
+ $form.find('input#fileURL').val('');
+ $form.find('input#fileText').val('');
+ $('.richText-toolbar li.is-selected').removeClass("is-selected");
+ }
+ }
+ });
+
+
+ // adding table
+ $(document).on("click", "#richText-Table button.btn", function(event) {
+ event.preventDefault();
+ var $button = $(this);
+ var $form = $button.parent('.richText-form-item').parent('.richText-form');
+ if($form.attr("data-editor") === editorID) {
+ // only for currently selected editor
+ var rows = $form.find('input#tableRows').val();
+ var columns = $form.find('input#tableColumns').val();
+
+ // set default values
+ if(!rows || rows <= 0) {
+ rows = 2;
+ }
+ if(!columns || columns <= 0) {
+ columns = 2;
+ }
+
+ // generate table
+ var html = '';
+ if(settings.useSingleQuotes === true) {
+ html = "
";
+ } else {
+ html = '';
+ }
+ for(var i = 1; i <= rows; i++) {
+ // start new row
+ html += '';
+ for(var n = 1; n <= columns; n++) {
+ // start new column in row
+ html += ' ';
+ }
+ html += ' ';
+ }
+ html += '
';
+
+ // write html in editor
+ restoreSelection(editorID, true);
+ pasteHTMLAtCaret(html);
+ // reset input values
+ $form.find('input#tableColumns').val('');
+ $form.find('input#tableRows').val('');
+ $('.richText-toolbar li.is-selected').removeClass("is-selected");
+ }
+ });
+
+ // opening / closing toolbar dropdown
+ $(document).on("click", function(event) {
+ var $clickedElement = $(event.target);
+
+ if($clickedElement.parents('.richText-toolbar').length === 0) {
+ // element not in toolbar
+ // ignore
+ } else if($clickedElement.hasClass("richText-dropdown-outer")) {
+ // closing dropdown by clicking inside the editor
+ $clickedElement.parent('a').parent('li').removeClass("is-selected");
+ } else if($clickedElement.find(".richText").length > 0) {
+ // closing dropdown by clicking outside of the editor
+ $('.richText-toolbar li').removeClass("is-selected");
+ } else if($clickedElement.parent().hasClass("richText-dropdown-close")) {
+ // closing dropdown by clicking on the close button
+ $('.richText-toolbar li').removeClass("is-selected");
+ } else if($clickedElement.hasClass("richText-btn") && $(event.target).children('.richText-dropdown-outer').length > 0) {
+ // opening dropdown by clicking on toolbar button
+ $clickedElement.parent('li').addClass("is-selected");
+
+ if($clickedElement.children('.fa,svg').hasClass("fa-link")) {
+ // put currently selected text in URL form to replace it
+ restoreSelection(editorID, false, true);
+ var selectedText = getSelectedText();
+ $clickedElement.find("input#urlText").val('');
+ $clickedElement.find("input#url").val('');
+ if(selectedText) {
+ $clickedElement.find("input#urlText").val(selectedText);
+ }
+ } else if($clickedElement.hasClass("fa-image")) {
+ // image
+ }
+ }
+ });
+
+ // Executing editor commands
+ $(document).on("click", ".richText-toolbar a[data-command]", function(event) {
+ var $button = $(this);
+ var $toolbar = $button.closest('.richText-toolbar');
+ var $editor = $toolbar.siblings('.richText-editor');
+ var id = $editor.attr("id");
+ if($editor.length > 0 && id === editorID && (!$button.parent("li").attr('data-disable') || $button.parent("li").attr('data-disable') === "false")) {
+ event.preventDefault();
+ var command = $(this).data("command");
+
+ if(command === "toggleCode") {
+ toggleCode($editor.attr("id"));
+ } else {
+ var option = null;
+ if ($(this).data('option')) {
+ option = $(this).data('option').toString();
+ if (option.match(/^h[1-6]$/)) {
+ command = "heading";
+ }
+ }
+
+ formatText(command, option, id);
+ if (command === "removeFormat") {
+ // remove HTML/CSS formatting
+ $editor.find('*').each(function() {
+ // remove all, but very few, attributes from the nodes
+ var keepAttributes = [
+ "id", "class",
+ "name", "action", "method",
+ "src", "align", "alt", "title",
+ "style", "webkitallowfullscreen", "mozallowfullscreen", "allowfullscreen",
+ "width", "height", "frameborder"
+ ];
+ var element = $(this);
+ var attributes = $.map(this.attributes, function(item) {
+ return item.name;
+ });
+ $.each(attributes, function(i, item) {
+ if(keepAttributes.indexOf(item) < 0 && item.substr(0, 5) !== 'data-') {
+ element.removeAttr(item);
+ }
+ });
+ if(element.prop('tagName') === "A") {
+ // remove empty URL tags
+ element.replaceWith(function() {
+ return $(' ', {html: $(this).html()});
+ });
+ }
+ });
+ formatText('formatBlock', 'div', id);
+ }
+ // clean up empty tags, which can be created while replacing formatting or when copy-pasting from other tools
+ $editor.find('div:empty,p:empty,li:empty,h1:empty,h2:empty,h3:empty,h4:empty,h5:empty,h6:empty').remove();
+ $editor.find('h1,h2,h3,h4,h5,h6').unwrap('h1,h2,h3,h4,h5,h6');
+ }
+ }
+ // close dropdown after click
+ $button.parents('li.is-selected').removeClass('is-selected');
+ });
+
+
+
+ /** INTERNAL METHODS **/
+
+ /**
+ * Format text in editor
+ * @param {string} command
+ * @param {string|null} option
+ * @param {string} editorID
+ * @private
+ */
+ function formatText(command, option, editorID) {
+ if (typeof option === "undefined") {
+ option = null;
+ }
+ // restore selection from before clicking on any button
+ doRestore(editorID);
+ // Temporarily enable designMode so that
+ // document.execCommand() will work
+ // document.designMode = "ON";
+ // Execute the command
+ if(command === "heading" && getSelectedText()) {
+ // IE workaround
+ pasteHTMLAtCaret('<' + option + '>' + getSelectedText() + '' + option + '>');
+ } else if(command === "fontSize" && parseInt(option) > 0) {
+ var selection = getSelectedText();
+ selection = (selection + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + ' ' + '$2');
+ var html = (settings.useSingleQuotes ? "" + selection + " " : '' + selection + ' ');
+ pasteHTMLAtCaret(html);
+ } else {
+ document.execCommand(command, false, option);
+ }
+ // Disable designMode
+ // document.designMode = "OFF";
+ }
+
+
+ /**
+ * Update textarea when updating editor
+ * @private
+ */
+ function updateTextarea() {
+ var $editor = $('#' + editorID);
+ var content = $editor.html();
+ if(settings.useSingleQuotes === true) {
+ content = changeAttributeQuotes(content);
+ }
+ $editor.siblings('.richText-initial').val(content);
+ }
+
+
+ /**
+ * Update editor when updating textarea
+ * @private
+ */
+ function updateEditor(editorID) {
+ var $editor = $('#' + editorID);
+ var content = $editor.siblings('.richText-initial').val();
+ $editor.html(content);
+ }
+
+
+ /**
+ * Save caret position and selection
+ * @return object
+ **/
+ function saveSelection(editorID) {
+ var containerEl = document.getElementById(editorID);
+ var range, start, end, type;
+ if(window.getSelection && document.createRange) {
+ var sel = window.getSelection && window.getSelection();
+ if (sel && sel.rangeCount > 0 && $(sel.anchorNode).parents('#' + editorID).length > 0) {
+ range = window.getSelection().getRangeAt(0);
+ var preSelectionRange = range.cloneRange();
+ preSelectionRange.selectNodeContents(containerEl);
+ preSelectionRange.setEnd(range.startContainer, range.startOffset);
+
+ start = preSelectionRange.toString().length;
+ end = (start + range.toString().length);
+
+ type = (start === end ? 'caret' : 'selection');
+ anchor = sel.anchorNode; //(type === "caret" && sel.anchorNode.tagName ? sel.anchorNode : false);
+ start = (type === 'caret' && anchor !== false ? 0 : preSelectionRange.toString().length);
+ end = (type === 'caret' && anchor !== false ? 0 : (start + range.toString().length));
+
+ return {
+ start: start,
+ end: end,
+ type: type,
+ anchor: anchor,
+ editorID: editorID
+ }
+ }
+ }
+ return (savedSelection ? savedSelection : {
+ start: 0,
+ end: 0
+ });
+ }
+
+
+ /**
+ * Restore selection
+ **/
+ function restoreSelection(editorID, media, url) {
+ var containerEl = document.getElementById(editorID);
+ var savedSel = savedSelection;
+ if(!savedSel) {
+ // fix selection if editor has not been focused
+ savedSel = {
+ 'start': 0,
+ 'end': 0,
+ 'type': 'caret',
+ 'editorID': editorID,
+ 'anchor': $('#' + editorID).children('div')[0]
+ };
+ }
+
+ if(savedSel.editorID !== editorID) {
+ return false;
+ } else if(media === true) {
+ containerEl = (savedSel.anchor ? savedSel.anchor : containerEl); // fix selection issue
+ } else if(url === true) {
+ if(savedSel.start === 0 && savedSel.end === 0) {
+ containerEl = (savedSel.anchor ? savedSel.anchor : containerEl); // fix selection issue
+ }
+ }
+
+ if (window.getSelection && document.createRange) {
+ var charIndex = 0, range = document.createRange();
+ if(!range || !containerEl) { window.getSelection().removeAllRanges(); return true; }
+ range.setStart(containerEl, 0);
+ range.collapse(true);
+ var nodeStack = [containerEl], node, foundStart = false, stop = false;
+
+ while (!stop && (node = nodeStack.pop())) {
+ if (node.nodeType === 3) {
+ var nextCharIndex = charIndex + node.length;
+ if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
+ range.setStart(node, savedSel.start - charIndex);
+ foundStart = true;
+ }
+ if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
+ range.setEnd(node, savedSel.end - charIndex);
+ stop = true;
+ }
+ charIndex = nextCharIndex;
+ } else {
+ var i = node.childNodes.length;
+ while (i--) {
+ nodeStack.push(node.childNodes[i]);
+ }
+ }
+ }
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+
+
+
+ /**
+ * Save caret position and selection
+ * @return object
+ **/
+ /*
+ function saveSelection(editorID) {
+ var containerEl = document.getElementById(editorID);
+ var start;
+ if (window.getSelection && document.createRange) {
+ var sel = window.getSelection && window.getSelection();
+ if (sel && sel.rangeCount > 0) {
+ var range = window.getSelection().getRangeAt(0);
+ var preSelectionRange = range.cloneRange();
+ preSelectionRange.selectNodeContents(containerEl);
+ preSelectionRange.setEnd(range.startContainer, range.startOffset);
+ start = preSelectionRange.toString().length;
+
+ return {
+ start: start,
+ end: start + range.toString().length,
+ editorID: editorID
+ }
+ } else {
+ return (savedSelection ? savedSelection : {
+ start: 0,
+ end: 0
+ });
+ }
+ } else if (document.selection && document.body.createTextRange) {
+ var selectedTextRange = document.selection.createRange();
+ var preSelectionTextRange = document.body.createTextRange();
+ preSelectionTextRange.moveToElementText(containerEl);
+ preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
+ start = preSelectionTextRange.text.length;
+
+ return {
+ start: start,
+ end: start + selectedTextRange.text.length,
+ editorID: editorID
+ };
+ }
+ }
+ */
+
+ /**
+ * Restore selection
+ **/
+ /*
+ function restoreSelection(editorID) {
+ var containerEl = document.getElementById(editorID);
+ var savedSel = savedSelection;
+ if(savedSel.editorID !== editorID) {
+ return false;
+ }
+ if (window.getSelection && document.createRange) {
+ var charIndex = 0, range = document.createRange();
+ range.setStart(containerEl, 0);
+ range.collapse(true);
+ var nodeStack = [containerEl], node, foundStart = false, stop = false;
+
+ while (!stop && (node = nodeStack.pop())) {
+ if (node.nodeType === 3) {
+ var nextCharIndex = charIndex + node.length;
+ if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
+ range.setStart(node, savedSel.start - charIndex);
+ foundStart = true;
+ }
+ if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
+ range.setEnd(node, savedSel.end - charIndex);
+ stop = true;
+ }
+ charIndex = nextCharIndex;
+ } else {
+ var i = node.childNodes.length;
+ while (i--) {
+ nodeStack.push(node.childNodes[i]);
+ }
+ }
+ }
+ var sel = window.getSelection();
+ sel.removeAllRanges();
+ sel.addRange(range);
+ } else if (document.selection && document.body.createTextRange) {
+ var textRange = document.body.createTextRange();
+ textRange.moveToElementText(containerEl);
+ textRange.collapse(true);
+ textRange.moveEnd("character", savedSel.end);
+ textRange.moveStart("character", savedSel.start);
+ textRange.select();
+ }
+ }
+ */
+
+ /**
+ * Enables tabbing/shift-tabbing between contentEditable table cells
+ * @param {Window} win - Active window context.
+ * @param {Event} e - jQuery Event object for the keydown that fired.
+ */
+ function tabifyEditableTable(win, e) {
+
+ if (e.keyCode !== 9) {
+ return false;
+ }
+
+ var sel;
+ if (win.getSelection) {
+ sel = win.getSelection();
+ if (sel.rangeCount > 0) {
+
+ var textNode = null,
+ direction = null;
+
+ if (!e.shiftKey) {
+ direction = "next";
+ textNode = (sel.focusNode.nodeName === "TD")
+ ? (sel.focusNode.nextSibling != null)
+ ? sel.focusNode.nextSibling
+ : (sel.focusNode.parentNode.nextSibling != null)
+ ? sel.focusNode.parentNode.nextSibling.childNodes[0]
+ : null
+ : (sel.focusNode.parentNode.nextSibling != null)
+ ? sel.focusNode.parentNode.nextSibling
+ : (sel.focusNode.parentNode.parentNode.nextSibling != null)
+ ? sel.focusNode.parentNode.parentNode.nextSibling.childNodes[0]
+ : null;
+ } else {
+ direction = "previous";
+ textNode = (sel.focusNode.nodeName === "TD")
+ ? (sel.focusNode.previousSibling != null)
+ ? sel.focusNode.previousSibling
+ : (sel.focusNode.parentNode.previousSibling != null)
+ ? sel.focusNode.parentNode.previousSibling.childNodes[sel.focusNode.parentNode.previousSibling.childNodes.length - 1]
+ : null
+ : (sel.focusNode.parentNode.previousSibling != null)
+ ? sel.focusNode.parentNode.previousSibling
+ : (sel.focusNode.parentNode.parentNode.previousSibling != null)
+ ? sel.focusNode.parentNode.parentNode.previousSibling.childNodes[sel.focusNode.parentNode.parentNode.previousSibling.childNodes.length - 1]
+ : null;
+ }
+
+ if (textNode != null) {
+ sel.collapse(textNode, Math.min(textNode.length, sel.focusOffset + 1));
+ if (textNode.textContent != null) {
+ sel.selectAllChildren(textNode);
+ }
+ e.preventDefault();
+ return true;
+ } else if(textNode === null && direction === "next" && sel.focusNode.nodeName === "TD") {
+ // add new row on TAB if arrived at the end of the row
+ var $table = $(sel.focusNode).parents("table");
+ var cellsPerLine = $table.find("tr").first().children("td").length;
+ var $tr = $(" ");
+ var $td = $(" ");
+ for(var i = 1; i <= cellsPerLine; i++) {
+ $tr.append($td.clone());
+ }
+ $table.append($tr);
+ // simulate tabing through table
+ tabifyEditableTable(window, {keyCode: 9, shiftKey: false, preventDefault: function(){}});
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the text from the current selection
+ * @private
+ * @return {string|boolean}
+ */
+ function getSelectedText() {
+ var range;
+ if (window.getSelection) { // all browsers, except IE before version 9
+ range = window.getSelection();
+ return range.toString() ? range.toString() : range.focusNode.nodeValue;
+ } else if (document.selection.createRange) { // Internet Explorer
+ range = document.selection.createRange();
+ return range.text;
+ }
+ return false;
+ }
+
+ /**
+ * Save selection
+ */
+ function doSave(editorID) {
+ var $textarea = $('.richText-editor#' + editorID).siblings('.richText-initial');
+ addHistory($textarea.val(), editorID);
+ savedSelection = saveSelection(editorID);
+ }
+
+ /**
+ * Add to history
+ * @param val Editor content
+ * @param id Editor ID
+ */
+ function addHistory(val, id) {
+ if(!history[id]) {
+ return false;
+ }
+ if(history[id].length-1 > historyPosition[id]) {
+ history[id].length = historyPosition[id] + 1;
+ }
+
+ if(history[id][history[id].length-1] !== val) {
+ history[id].push(val);
+ }
+
+ historyPosition[id] = history[id].length-1;
+ setHistoryButtons(id);
+ }
+
+ function setHistoryButtons(id) {
+ if(historyPosition[id] <= 0) {
+ $editor.find(".richText-undo").addClass("is-disabled");
+ } else {
+ $editor.find(".richText-undo").removeClass("is-disabled");
+ }
+
+ if(historyPosition[id] >= history[id].length-1 || history[id].length === 0) {
+ $editor.find(".richText-redo").addClass("is-disabled");
+ } else {
+ $editor.find(".richText-redo").removeClass("is-disabled");
+ }
+ }
+
+ /**
+ * Undo
+ * @param $editor
+ */
+ function undo($editor) {
+ var id = $editor.children('.richText-editor').attr('id');
+ historyPosition[id]--;
+ if(!historyPosition[id] && historyPosition[id] !== 0) {
+ return false;
+ }
+ var value = history[id][historyPosition[id]];
+ $editor.find('textarea').val(value);
+ $editor.find('.richText-editor').html(value);
+ setHistoryButtons(id);
+ }
+
+ /**
+ * Undo
+ * @param $editor
+ */
+ function redo($editor) {
+ var id = $editor.children('.richText-editor').attr('id');
+ historyPosition[id]++;
+ if(!historyPosition[id] && historyPosition[id] !== 0) {
+ return false;
+ }
+ var value = history[id][historyPosition[id]];
+ $editor.find('textarea').val(value);
+ $editor.find('.richText-editor').html(value);
+ setHistoryButtons(id);
+ }
+
+ /**
+ * Restore selection
+ */
+ function doRestore(id) {
+ if(savedSelection) {
+ restoreSelection((id ? id : savedSelection.editorID));
+ }
+ }
+
+ /**
+ * Paste HTML at caret position
+ * @param {string} html HTML code
+ * @private
+ */
+ function pasteHTMLAtCaret(html) {
+ // add HTML code for Internet Explorer
+ var sel, range;
+ if (window.getSelection) {
+ // IE9 and non-IE
+ sel = window.getSelection();
+ if (sel.getRangeAt && sel.rangeCount) {
+ range = sel.getRangeAt(0);
+ range.deleteContents();
+
+ // Range.createContextualFragment() would be useful here but is
+ // only relatively recently standardized and is not supported in
+ // some browsers (IE9, for one)
+ var el = document.createElement("div");
+ el.innerHTML = html;
+ var frag = document.createDocumentFragment(), node, lastNode;
+ while ( (node = el.firstChild) ) {
+ lastNode = frag.appendChild(node);
+ }
+ range.insertNode(frag);
+
+ // Preserve the selection
+ if (lastNode) {
+ range = range.cloneRange();
+ range.setStartAfter(lastNode);
+ range.collapse(true);
+ sel.removeAllRanges();
+ sel.addRange(range);
+ }
+ }
+ } else if (document.selection && document.selection.type !== "Control") {
+ // IE < 9
+ document.selection.createRange().pasteHTML(html);
+ }
+ }
+
+
+ /**
+ * Change quotes around HTML attributes
+ * @param {string} string
+ * @return {string}
+ */
+ function changeAttributeQuotes(string) {
+ if(!string) {
+ return '';
+ }
+
+ var regex;
+ var rstring;
+ if(settings.useSingleQuotes === true) {
+ regex = /\s+(\w+\s*=\s*(["][^"]*["])|(['][^']*[']))+/g;
+ rstring = string.replace(regex, function($0,$1,$2){
+ if(!$2) {return $0;}
+ return $0.replace($2, $2.replace(/\"/g, "'"));
+ });
+ } else {
+ regex = /\s+(\w+\s*=\s*(['][^']*['])|(["][^"]*["]))+/g;
+ rstring = string.replace(regex, function($0,$1,$2){
+ if(!$2) {return $0;}
+ return $0.replace($2, $2.replace(/'/g, '"'));
+ });
+ }
+ return rstring;
+ }
+
+
+ /**
+ * Load colors for font or background
+ * @param {string} command Command
+ * @returns {string}
+ * @private
+ */
+ function loadColors(command) {
+ var colors = [];
+ var result = '';
+
+ colors["#FFFFFF"] = settings.translations.white;
+ colors["#000000"] = settings.translations.black;
+ colors["#7F6000"] = settings.translations.brown;
+ colors["#938953"] = settings.translations.beige;
+ colors["#1F497D"] = settings.translations.darkBlue;
+ colors["blue"] = settings.translations.blue;
+ colors["#4F81BD"] = settings.translations.lightBlue;
+ colors["#953734"] = settings.translations.darkRed;
+ colors["red"] = settings.translations.red;
+ colors["#4F6128"] = settings.translations.darkGreen;
+ colors["green"] = settings.translations.green;
+ colors["#3F3151"] = settings.translations.purple;
+ colors["#31859B"] = settings.translations.darkTurquois;
+ colors["#4BACC6"] = settings.translations.turquois;
+ colors["#E36C09"] = settings.translations.darkOrange;
+ colors["#F79646"] = settings.translations.orange;
+ colors["#FFFF00"] = settings.translations.yellow;
+
+ if(settings.colors && settings.colors.length > 0) {
+ colors = settings.colors;
+ }
+
+ for (var i in colors) {
+ result += ' ';
+ }
+ return result;
+ }
+
+
+ /**
+ * Toggle (show/hide) code or editor
+ * @private
+ */
+ function toggleCode(editorID) {
+ doRestore(editorID);
+ if($editor.find('.richText-editor').is(":visible")) {
+ // show code
+ $editor.find('.richText-initial').show();
+ $editor.find('.richText-editor').hide();
+ // disable non working buttons
+ $('.richText-toolbar').find('.richText-btn').each(function() {
+ if($(this).children('.fa-code').length === 0) {
+ $(this).parent('li').attr("data-disable", "true");
+ }
+ });
+ convertCaretPosition(editorID, savedSelection);
+ } else {
+ // show editor
+ $editor.find('.richText-initial').hide();
+ $editor.find('.richText-editor').show();
+ convertCaretPosition(editorID, savedSelection, true);
+ // enable all buttons again
+ $('.richText-toolbar').find('li').removeAttr("data-disable");
+ }
+ }
+
+
+ /**
+ * Convert caret position from editor to code view (or in reverse)
+ * @param {string} editorID
+ * @param {object} selection
+ * @param {boolean} reverse
+ **/
+ function convertCaretPosition(editorID, selection, reverse) {
+ var $editor = $('#' + editorID);
+ var $textarea = $editor.siblings(".richText-initial");
+
+ var code = $textarea.val();
+ if(!selection || !code) {
+ return {start: 0, end: 0};
+ }
+
+ if(reverse === true) {
+ savedSelection = {start: $editor.text().length, end: $editor.text().length, editorID: editorID};
+ restoreSelection(editorID);
+ return true;
+ }
+ selection.node = $textarea[0];
+ var states = {start: false, end: false, tag: false, isTag: false, tagsCount: 0, isHighlight: (selection.start !== selection.end)};
+ for(var i = 0; i < code.length; i++) {
+ if(code[i] === "<") {
+ // HTML tag starts
+ states.isTag = true;
+ states.tag = false;
+ states.tagsCount++;
+ } else if(states.isTag === true && code[i] !== ">") {
+ states.tagsCount++;
+ } else if(states.isTag === true && code[i] === ">") {
+ states.isTag = false;
+ states.tag = true;
+ states.tagsCount++;
+ } else if(states.tag === true) {
+ states.tag = false;
+ }
+
+ if(!reverse) {
+ if((selection.start + states.tagsCount) <= i && states.isHighlight && !states.isTag && !states.tag && !states.start) {
+ selection.start = i;
+ states.start = true;
+ } else if((selection.start + states.tagsCount) <= i+1 && !states.isHighlight && !states.isTag && !states.tag && !states.start) {
+ selection.start = i+1;
+ states.start = true;
+ }
+ if((selection.end + states.tagsCount) <= i+1 && !states.isTag && !states.tag && !states.end) {
+ selection.end = i+1;
+ states.end = true;
+ }
+ }
+
+ }
+ createSelection(selection.node, selection.start, selection.end);
+ return selection;
+ }
+
+ /**
+ * Create selection on node element
+ * @param {Node} field
+ * @param {int} start
+ * @param {int} end
+ **/
+ function createSelection(field, start, end) {
+ if( field.createTextRange ) {
+ var selRange = field.createTextRange();
+ selRange.collapse(true);
+ selRange.moveStart('character', start);
+ selRange.moveEnd('character', end);
+ selRange.select();
+ field.focus();
+ } else if( field.setSelectionRange ) {
+ field.focus();
+ field.setSelectionRange(start, end);
+ } else if( typeof field.selectionStart != 'undefined' ) {
+ field.selectionStart = start;
+ field.selectionEnd = end;
+ field.focus();
+ }
+ }
+
+
+ /**
+ * Get video embed code from URL
+ * @param {string} url Video URL
+ * @param {string} size Size in the form of widthxheight
+ * @return {string|boolean}
+ * @private
+ **/
+ function getVideoCode(url, size) {
+ var video = getVideoID(url);
+ var responsive = false, success = false;
+
+ if(!video) {
+ // video URL not supported
+ return false;
+ }
+
+ if(!size) {
+ size = "640x360";
+ size = size.split("x");
+ } else if(size !== "responsive") {
+ size = size.split("x");
+ } else {
+ responsive = true;
+ size = "640x360";
+ size = size.split("x");
+ }
+
+ var html = ' ';
+ if(responsive === true) {
+ html += '';
+ }
+ var allowfullscreen = 'webkitallowfullscreen mozallowfullscreen allowfullscreen';
+
+ if(video.platform === "YouTube") {
+ var youtubeDomain = (settings.youtubeCookies ? 'www.youtube.com' : 'www.youtube-nocookie.com');
+ html += '';
+ success = true;
+ } else if(video.platform === "Vimeo") {
+ html += '';
+ success = true;
+ } else if(video.platform === "Facebook") {
+ html += '';
+ success = true;
+ } else if(video.platform === "Dailymotion") {
+ html += '';
+ success = true;
+ }
+
+ if(responsive === true) {
+ html += '
';
+ }
+ html += ' ';
+
+ if(success) {
+ return html;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the unique video ID
+ * @param {string} url
+ * return {object|boolean}
+ **/
+ function getVideoID(url) {
+ var vimeoRegExp = /(?:http?s?:\/\/)?(?:www\.)?(?:vimeo\.com)\/?(.+)/;
+ var youtubeRegExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
+ var facebookRegExp = /(?:http?s?:\/\/)?(?:www\.)?(?:facebook\.com)\/.*\/videos\/[0-9]+/;
+ var dailymotionRegExp = /(?:http?s?:\/\/)?(?:www\.)?(?:dailymotion\.com)\/video\/([a-zA-Z0-9]+)/;
+ var youtubeMatch = url.match(youtubeRegExp);
+ var vimeoMatch = url.match(vimeoRegExp);
+ var facebookMatch = url.match(facebookRegExp);
+ var dailymotionMatch = url.match(dailymotionRegExp);
+
+ if (youtubeMatch && youtubeMatch[2].length === 11) {
+ return {
+ "platform": "YouTube",
+ "id": youtubeMatch[2]
+ };
+ } else if(vimeoMatch && vimeoMatch[1]) {
+ return {
+ "platform": "Vimeo",
+ "id": vimeoMatch[1]
+ };
+ } else if(facebookMatch && facebookMatch[0]) {
+ return {
+ "platform": "Facebook",
+ "id" : facebookMatch[0]
+ };
+ } else if(dailymotionMatch && dailymotionMatch[1]) {
+ return {
+ "platform": "Dailymotion",
+ "id" : dailymotionMatch[1]
+ };
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Fix the first line as by default the first line has no tag container
+ */
+ function fixFirstLine() {
+ if($editor && !$editor.find(".richText-editor").html()) {
+ // set first line with the right tags
+ if(settings.useParagraph !== false) {
+ $editor.find(".richText-editor").html('
');
+ } else {
+ //$editor.find(".richText-editor").html('
');
+ $editor.find(".richText-editor").html('');
+ }
+ } else {
+ // replace tags, to force or
tags and fix issues
+ if(settings.useParagraph !== false) {
+ $editor.find(".richText-editor").find('div:not(.videoEmbed)').replaceWith(function() {
+ return $('
', {html: $(this).html()});
+ });
+ } else {
+ $editor.find(".richText-editor").find('p').replaceWith(function() {
+ return $('
', {html: $(this).html()});
+ });
+ }
+ }
+ updateTextarea();
+ }
+
+ return $(this);
+ };
+
+ $.fn.unRichText = function( options ) {
+
+ // set default options
+ // and merge them with the parameter options
+ var settings = $.extend({
+ delay: 0 // delay in ms
+ }, options);
+
+ var $editor, $textarea, $main;
+ var $el = $(this);
+
+ /**
+ * Initialize undoing RichText and call remove() method
+ */
+ function init() {
+
+ if($el.hasClass('richText')) {
+ $main = $el;
+ } else if($el.hasClass('richText-initial') || $el.hasClass('richText-editor')) {
+ $main = $el.parents('.richText');
+ }
+
+ if(!$main) {
+ // node element does not correspond to RichText elements
+ return false;
+ }
+
+ $editor = $main.find('.richText-editor');
+ $textarea = $main.find('.richText-initial');
+
+ if(parseInt(settings.delay) > 0) {
+ // a delay has been set
+ setTimeout(remove, parseInt(settings.delay));
+ } else {
+ remove();
+ }
+ }
+ init();
+
+ /**
+ * Remove RichText elements
+ */
+ function remove() {
+ $main.find('.richText-toolbar').remove();
+ $main.find('.richText-editor').remove();
+ $textarea
+ .unwrap('.richText')
+ .data('editor', 'richText')
+ .removeClass('richText-initial')
+ .show();
+ }
+
+ };
+
+}( jQuery ));
\ No newline at end of file
diff --git a/js/scrollables.js b/js/scrollables.js
new file mode 100644
index 0000000..1bf98f5
--- /dev/null
+++ b/js/scrollables.js
@@ -0,0 +1,31 @@
+const scrollButtons = `
+
+
+
+
+
+
+
+`
+
+document.body.insertAdjacentHTML('beforeend', scrollButtons);
+
+const scroll_up = document.querySelector('#scroll-up');
+const scroll_down = document.querySelector('#scroll-down');
+
+scroll_up.style.transition = scroll_down.style.transition = 'display 1.5s ease-in-out';
+scroll_up.style.display = scroll_down.style.display = 'none';
+
+scroll_up.addEventListener('click', () =>
+ window.scrollTo({ top: 0, behavior: 'smooth' }))
+
+
+scroll_down.addEventListener('click', () =>
+ window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }))
+
+const check = () => {
+ scroll_down.style.display = (window.scrollY + window.innerHeight) > document.body.scrollHeight * .8 ? 'none' : 'block'
+ scroll_up.style.display = (window.scrollY) < document.body.scrollHeight * .2 ? 'none' : 'block'
+}
+
+['scroll', 'resize'].forEach(e => window.addEventListener(e, check))
diff --git a/js/sidebarmenu.js b/js/sidebarmenu.js
new file mode 100644
index 0000000..4e1e211
--- /dev/null
+++ b/js/sidebarmenu.js
@@ -0,0 +1,49 @@
+/*
+ * JQuery para el manejo de menu
+ */
+
+$('#dismiss, .overlay').on('click', function () {
+ // hide sidebar
+ $('#sidebar').removeClass('active');
+ // hide overlay
+ $('.overlay').removeClass('active');
+ $('.menu').css('visibility', 'visible');
+});
+
+$('#sidebarCollapse').on('click', function () {
+ // open sidebar
+ $('#sidebar').addClass('active');
+ // fade in the overlay
+ $('.overlay').addClass('active');
+ $('.menu').css('visibility', 'hidden');
+ //$('.collapse.in').toggleClass('in');
+ $('a[aria-expanded=true]').attr('aria-expanded', 'false');
+});
+
+/*
+var Nightly = new Nightly(true, {
+ //body: "backgorund color", // Default: #282828
+ //texts: "texts color", // Default: #f5f5f5
+ //inputs: {
+ // color: "text color inside inputs", // Default: #f5f5f5
+ // backgroundColor: "background color" // Default #313131
+ //},
+ //buttons: {
+ // color: "button's text color", // Default: #f5f5f5
+ // backgroundColor: "button's backgournd color" // #757575
+ //},
+ links: "#ffffff", // Default: #009688
+ classes: [// Classes to apply when enabling the dark mode on certain elements
+ { apply: 'bg-head-dark', to: 'bg-head', },
+ { apply: 'form-control-dark', to: 'form-control', },
+ { apply: 'subMenu-dark', to: 'subMenu', },
+ { apply: 'sistema.text-white', to: 'sistema.text-secondary', },
+ ]
+});
+
+if($(".fa-adjust")){
+ $(".fa-adjust").click(function(){
+ Nightly.toggle();
+ });
+}*/
+
diff --git a/js/toggle.js b/js/toggle.js
new file mode 100644
index 0000000..76658d8
--- /dev/null
+++ b/js/toggle.js
@@ -0,0 +1,187 @@
+/*\
+|*| ========================================================================
+|*| Bootstrap Toggle: bootstrap4-toggle.js v3.6.1
+|*| https://gitbrent.github.io/bootstrap4-toggle/
+|*| ========================================================================
+|*| Copyright 2018-2019 Brent Ely
+|*| Licensed under MIT
+|*| ========================================================================
+\*/
+
++function ($) {
+ 'use strict';
+
+ // TOGGLE PUBLIC CLASS DEFINITION
+ // ==============================
+
+ var Toggle = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, this.defaults(), options)
+ this.render()
+ }
+
+ Toggle.VERSION = '3.7.0-beta'
+
+ Toggle.DEFAULTS = {
+ on: 'On',
+ off: 'Off',
+ onstyle: 'primary',
+ offstyle: 'light',
+ size: 'normal',
+ style: '',
+ width: null,
+ height: null
+ }
+
+ Toggle.prototype.defaults = function() {
+ return {
+ on: this.$element.attr('data-on') || Toggle.DEFAULTS.on,
+ off: this.$element.attr('data-off') || Toggle.DEFAULTS.off,
+ onstyle: this.$element.attr('data-onstyle') || Toggle.DEFAULTS.onstyle,
+ offstyle: this.$element.attr('data-offstyle') || Toggle.DEFAULTS.offstyle,
+ size: this.$element.attr('data-size') || Toggle.DEFAULTS.size,
+ style: this.$element.attr('data-style') || Toggle.DEFAULTS.style,
+ width: this.$element.attr('data-width') || Toggle.DEFAULTS.width,
+ height: this.$element.attr('data-height') || Toggle.DEFAULTS.height
+ }
+ }
+
+ Toggle.prototype.render = function () {
+ this._onstyle = 'btn-' + this.options.onstyle
+ this._offstyle = 'btn-' + this.options.offstyle
+ var size
+ = this.options.size === 'large' || this.options.size === 'lg' ? 'btn-lg'
+ : this.options.size === 'small' || this.options.size === 'sm' ? 'btn-sm'
+ : this.options.size === 'mini' || this.options.size === 'xs' ? 'btn-xs'
+ : ''
+ var $toggleOn = $('
').html(this.options.on)
+ .addClass(this._onstyle + ' ' + size)
+ var $toggleOff = $('').html(this.options.off)
+ .addClass(this._offstyle + ' ' + size)
+ var $toggleHandle = $('')
+ .addClass(size)
+ var $toggleGroup = $('')
+ .append($toggleOn, $toggleOff, $toggleHandle)
+ var $toggle = $('
')
+ .addClass( this.$element.prop('checked') ? this._onstyle : this._offstyle+' off' )
+ .addClass(size).addClass(this.options.style)
+
+ this.$element.wrap($toggle)
+ $.extend(this, {
+ $toggle: this.$element.parent(),
+ $toggleOn: $toggleOn,
+ $toggleOff: $toggleOff,
+ $toggleGroup: $toggleGroup
+ })
+ this.$toggle.append($toggleGroup)
+
+ var width = this.options.width || Math.max($toggleOn.outerWidth(), $toggleOff.outerWidth())+($toggleHandle.outerWidth()/2)
+ var height = this.options.height || Math.max($toggleOn.outerHeight(), $toggleOff.outerHeight())
+ $toggleOn.addClass('toggle-on')
+ $toggleOff.addClass('toggle-off')
+ this.$toggle.css({ width: width, height: height })
+ if (this.options.height) {
+ $toggleOn.css('line-height', $toggleOn.height() + 'px')
+ $toggleOff.css('line-height', $toggleOff.height() + 'px')
+ }
+ this.update(true)
+ this.trigger(true)
+ }
+
+ Toggle.prototype.toggle = function () {
+ if (this.$element.prop('checked')) this.off()
+ else this.on()
+ }
+
+ Toggle.prototype.on = function (silent) {
+ if (this.$element.prop('disabled')) return false
+ this.$toggle.removeClass(this._offstyle + ' off').addClass(this._onstyle)
+ this.$element.prop('checked', true)
+ if (!silent) this.trigger()
+ }
+
+ Toggle.prototype.off = function (silent) {
+ if (this.$element.prop('disabled')) return false
+ this.$toggle.removeClass(this._onstyle).addClass(this._offstyle + ' off')
+ this.$element.prop('checked', false)
+ if (!silent) this.trigger()
+ }
+
+ Toggle.prototype.enable = function () {
+ this.$toggle.removeClass('disabled')
+ this.$toggle.removeAttr('disabled')
+ this.$element.prop('disabled', false)
+ }
+
+ Toggle.prototype.disable = function () {
+ this.$toggle.addClass('disabled')
+ this.$toggle.attr('disabled', 'disabled')
+ this.$element.prop('disabled', true)
+ }
+
+ Toggle.prototype.update = function (silent) {
+ if (this.$element.prop('disabled')) this.disable()
+ else this.enable()
+ if (this.$element.prop('checked')) this.on(silent)
+ else this.off(silent)
+ }
+
+ Toggle.prototype.trigger = function (silent) {
+ this.$element.off('change.bs.toggle')
+ if (!silent) this.$element.change()
+ this.$element.on('change.bs.toggle', $.proxy(function() {
+ this.update()
+ }, this))
+ }
+
+ Toggle.prototype.destroy = function() {
+ this.$element.off('change.bs.toggle')
+ this.$toggleGroup.remove()
+ this.$element.removeData('bs.toggle')
+ this.$element.unwrap()
+ }
+
+ // TOGGLE PLUGIN DEFINITION
+ // ========================
+
+ function Plugin(option) {
+ var optArg = Array.prototype.slice.call( arguments, 1 )[0]
+
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.toggle')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.toggle', (data = new Toggle(this, options)))
+ if (typeof option === 'string' && data[option] && typeof optArg === 'boolean') data[option](optArg)
+ else if (typeof option === 'string' && data[option]) data[option]()
+ //else if (option && !data[option]) console.log('bootstrap-toggle: error: method `'+ option +'` does not exist!');
+ })
+ }
+
+ var old = $.fn.bootstrapToggle
+
+ $.fn.bootstrapToggle = Plugin
+ $.fn.bootstrapToggle.Constructor = Toggle
+
+ // TOGGLE NO CONFLICT
+ // ==================
+
+ $.fn.toggle.noConflict = function () {
+ $.fn.bootstrapToggle = old
+ return this
+ }
+
+ // TOGGLE DATA-API
+ // ===============
+
+ $(function() {
+ $('input[type=checkbox][data-toggle^=toggle]').bootstrapToggle()
+ })
+
+ $(document).on('click.bs.toggle', 'div[data-toggle^=toggle]', function(e) {
+ var $checkbox = $(this).find('input[type=checkbox]')
+ $checkbox.bootstrapToggle('toggle')
+ e.preventDefault()
+ })
+}(jQuery);
diff --git a/js/util.js b/js/util.js
new file mode 100644
index 0000000..4862e33
--- /dev/null
+++ b/js/util.js
@@ -0,0 +1,105 @@
+/*
+ * utilidades js
+ */
+
+function trim(cadena){
+ for(i=0; i
=0; i=cadena.length-1){
+ if(cadena.charAt(i)==" ")
+ cadena=cadena.substring(0,i);
+ else
+ break;
+ }
+ return cadena;
+}
+
+function getDiaNombre(num){
+ switch(parseInt(num)){
+ case 0: return "Domingo";
+ case 1: return "Lunes";
+ case 2: return "Martes";
+ case 3: return "Miércoles";
+ case 4: return "Jueves";
+ case 5: return "Viernes";
+ case 6: return "Sábado";
+ }
+}
+
+function fechaGuion(fechaTxt){//de dd/mm/aaaa a aaaa-mm-dd
+ fechaTxt = trim(fechaTxt);
+ if(fechaTxt.substr(2,1) == "/" && fechaTxt.substr(5,1) == "/"){// dd/mm/aaaa
+ var fechaArr = fechaTxt.split("/");
+ return fechaArr[2]+"-"+fechaArr[1]+"-"+fechaArr[0];
+ }
+ if(fechaTxt.substr(4,1) == "-" && fechaTxt.substr(7,1) == "-")// aaaa-mm-dd
+ return fechaTxt;
+ return "";
+
+}
+
+function fechaObjeto(fechaTxt){//de dd/mm/aaaa a aaaa-mm-dd
+ fechaTxt = trim(fechaTxt);
+ if(fechaTxt.substr(2,1) == "/" && fechaTxt.substr(5,1) == "/"){// dd/mm/aaaa
+ var fechaArr = fechaTxt.split("/");
+ return new Date(parseInt(fechaArr[2]), parseInt(fechaArr[1])-1, parseInt(fechaArr[0]) );
+ }
+ if(fechaTxt.substr(4,1) == "-" && fechaTxt.substr(7,1) == "-"){// aaaa-mm-dd
+ var fechaArr = fechaTxt.split("-");
+ return new Date(parseInt(fechaArr[0]), parseInt(fechaArr[1])-1, parseInt(fechaArr[2]) );
+ }
+ return false;
+
+}
+
+function validaFecha(fechaTxt){
+ if(fechaTxt.charAt(4) == "-" && fechaTxt.charAt(7) == "-"){//yyyy-mm-dd
+ var fechaArr = fechaTxt.split("-");
+ var ano= fechaArr[0];
+ var mes= fechaArr[1];
+ var dia= fechaArr[2];
+ }
+ if(fechaTxt.charAt(2) == "/" && fechaTxt.charAt(5) == "/"){//dd-mm-aaaa
+ var fechaArr = fechaTxt.split("/");
+ var ano= fechaArr[2];
+ var mes= fechaArr[1];
+ var dia= fechaArr[0];
+ }
+
+ var d = new Date();
+ var anoActual = d.getFullYear();
+ if (isNaN(ano) || ano.length < 4 || parseInt(ano, 10) < (anoActual-1)){ return false; }
+ if (isNaN(mes) || parseInt(mes, 10) < 1 || parseInt(mes, 10) > 12){ return false; }
+ if (isNaN(dia) || parseInt(dia, 10) < 1 || parseInt(dia, 10) > 31){ return false; }
+ if (mes == 4 || mes == 6 || mes == 9 || mes== 11) {
+ if (dia > 30) { return false; }
+ } else{
+ if (mes == 2) {
+ if(dia <= 28 )
+ return true;
+ else{
+ if ((ano % 4 == 0) && dia == 29) return true;
+ else return false;
+ }
+ }
+ }
+ return true;
+}
+
+function validaPass(str, vacio = false){
+ if(vacio && str == "") return true;
+ return str.match(/\S*(?=\S{5,})(?=\S*[a-zA-Z])(?=\S*[\d])(?=\S*[\W])\S*$/);
+}
+/*
+$('.toggle-password').click(function(){
+ var campo = $(this).parents(".form-group").find(".toggle-field");
+ if (campo.prop('type') === "password") {
+ campo.prop('type', 'text');
+ } else {
+ campo.prop('type', 'password');
+ }
+});*/
\ No newline at end of file
diff --git a/js/vista_forms.js b/js/vista_forms.js
new file mode 100644
index 0000000..70d0f5a
--- /dev/null
+++ b/js/vista_forms.js
@@ -0,0 +1,65 @@
+$(".date-picker").datepicker($.datepicker.regional["es"]);
+ $(".date-picker").datepicker({
+ dateFormat: "dd/mm/yyyy",
+ changeMonth: true,
+ });
+ $("#fecha_inicial").datepicker("option", "minDate", fecha_inicial);
+ $("#fecha_inicial").datepicker("option", "maxDate", limit);
+ $("#fecha_final").datepicker("option", "minDate", fecha_inicial);
+ $("#fecha_final").datepicker("option", "maxDate", limit);
+
+ var today = new Date();
+
+ var fecha_inicial = new Date(= isset($fecha_inicial) ? $fecha_inicial->format("Y, m-1, d") : date("Y, m-1, d", strtotime($periodo['inicio'])) ?>);
+ var fecha_final = new Date(= isset($fecha_final) ? $fecha_final->format("Y, m-1, d") : date("Y, m-1, d", strtotime($periodo['fin'])) ?>);
+ var limit = new Date(Math.min(today, fecha_final));
+ // if today is in the period, set the initial date to today
+ $("#fecha_inicial").datepicker("setDate", fecha_inicial);
+ $("#fecha_final").datepicker("setDate", today <= fecha_final ? today : fecha_final);
+
+ function reset_form() {
+ $("#fecha_inicial").datepicker("setDate", fecha_inicial);
+ $("#fecha_final").datepicker("setDate", today <= fecha_final ? today : fecha_final);
+ $("#dlcarrera").find("li").removeClass("selected");
+ $("#dlcarrera").find("li[data-value='0']").addClass("selected");
+ $("#dlmateria").find("li").removeClass("selected");
+ $("#dlmateria").find("li[data-value='0']").addClass("selected");
+ $("#filter_carrera").val("");
+ $("#filter_materia").val("");
+
+
+ console.log(`Todos los campos han sido limpiados.`);
+ }
+
+
+ disableDatalist("#filter_materia", true);
+
+
+
+
+ reset_form();
+
+ // $("#fecha_inicial").on("change", function() {
+ // var fecha_inicial = $("#fecha_inicial").datepicker("getDate");
+ // var fecha_final = $("#fecha_final").datepicker("getDate");
+ // if (fecha_final < fecha_inicial) {
+ // $("#fecha_final").datepicker("setDate", fecha_inicial);
+ // }
+ // $("#fecha_final").datepicker("option", "minDate", fecha_inicial);
+ // });
+
+ // $("#fecha_final").on("change", function() {
+ // var fecha_inicial = $("#fecha_inicial").datepicker("getDate");
+ // var fecha_final = $("#fecha_final").datepicker("getDate");
+ // if (fecha_final < fecha_inicial) {
+ // $("#fecha_inicial").datepicker("setDate", fecha_final);
+ // }
+ // $("#fecha_inicial").datepicker("option", "maxDate", fecha_final);
+ // });
+ // Datalist carrera then select materia
+ $(document).on('click', '#dlcarrera li', function() {
+ // if this is empty
+ // console.log($(this).attr('data-value'));
+ if ($(this).attr('data-value') == '0')
+ disableDatalist("#filter_materia", true);
+ });
\ No newline at end of file
diff --git a/main-old.php b/main-old.php
new file mode 100644
index 0000000..aa5b981
--- /dev/null
+++ b/main-old.php
@@ -0,0 +1,420 @@
+
+
+
+
+
+
+
+ Asistencia Profesores |
+ = $user->facultad['facultad'] ?? "Administrador"; ?>
+
+
+
+
+
+
+
+ user['nombre'],
+ $user->rol['rol'],
+ );
+ $nohorario = false;
+ $noduplicadas = false;
+ $juanita = 'imagenes/registrar.svg';
+ ?>
+
+
+
+
+
+
+
+
+
+
Hora actual -
+
+
+
+ No tienes clases en este horario
+
+
+ Recuerda: Solo se puede registrar entre
+ 30 minutos antes y
+ 20 minutos después.
+
+
+ Actualizar página
+
+
+
+
+
+
+
+ ";
+ } else {
+ foreach ($paginas as $pagina) {
+ if (is_null($pagina['pagina_ruta']))
+ continue;
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Asistencia
+
Nombre
+
+ Facultad
+
+ Materia
+ hh:mm
+
+ SALÓN: SAL
+ GRUPO: GPO
+
+
+
Actualizar
+ página
+
+
+
+
+
+
+
+
+
+
Hora actual -
+
+
+
+ No tienes clases en este horario
+
+
No hay ninguna clase registrada en este horario para
+
+ Recuerda: Solo se
+ puede registrar entre 20 minutos antes y 30 minutos después.
+ Actualizar
+ página
+
+
+
+
+
+
+
+
+
+
+
Se perdió la conexión a internet
+
Por el momento la conexión a
+ internet
+ está fallando, por favor inténtelo más tarde.
+
+
+
Loading...
+
+
Conectando
+
+
+
+
+
+
+
+
+
+
+
Error en el sistema
+
Se ha presentado un error en el
+ sistema, por
+ favor inténtelo más tarde y repórtelo al CAS .
+
+
+
+
+
+
+
+
+
+
La clave no está registrada
+
Revisa que la clave sea la correcta
+
No se pudo registrar asistencia
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/main.php b/main.php
new file mode 100644
index 0000000..9a2e379
--- /dev/null
+++ b/main.php
@@ -0,0 +1,434 @@
+
+
+
+
+
+
+
+ Asistencia Profesores |
+ = $user->facultad['facultad'] ?? "Administrador"; ?>
+
+
+
+
+
+
+
+ user['nombre'],
+ );
+ $nohorario = false;
+ $noduplicadas = false;
+ $juanita = 'imagenes/registrar.svg';
+ ?>
+
+
+
+
+
+
+
+
+
+
Hora actual -
+
+
+
+ No tienes clases en este horario
+
+
+ Recuerda: Solo se puede registrar entre
+ 30 minutos antes y
+ 20 minutos después.
+
+
+ Actualizar página
+
+
+
+
+
+
+
+ ";
+ } else {
+ foreach ($paginas as $pagina) {
+ if (is_null($pagina['pagina_ruta']))
+ continue;
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Asistencia
+
Nombre
+
+ Facultad
+
+ Materia
+ hh:mm
+
+ SALÓN: SAL
+ GRUPO: GPO
+
+
+
Actualizar
+ página
+
+
+
+
+
+
+
+
+
+
Hora actual -
+
+
+
+ No tienes clases en este horario
+
+
No hay ninguna clase registrada en este horario para
+
+ Recuerda: Solo se
+ puede registrar entre 20 minutos antes y 30 minutos después.
+ Actualizar
+ página
+
+
+
+
+
+
+
+
+
+
+
Se perdió la conexión a internet
+
Por el momento la conexión a
+ internet
+ está fallando, por favor inténtelo más tarde.
+
+
+
Loading...
+
+
Conectando
+
+
+
+
+
+
+
+
+
+
+
Error en el sistema
+
Se ha presentado un error en el
+ sistema, por
+ favor inténtelo más tarde y repórtelo al CAS .
+
+
+
+
+
+
+
+
+
+
La clave no está registrada
+
Revisa que la clave sea la correcta
+
No se pudo registrar asistencia
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/salir.php b/salir.php
new file mode 100644
index 0000000..b9dedb7
--- /dev/null
+++ b/salir.php
@@ -0,0 +1,5 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
+ *
+ * $loader = new \Composer\Autoload\ClassLoader();
+ *
+ * // register classes with namespaces
+ * $loader->add('Symfony\Component', __DIR__.'/component');
+ * $loader->add('Symfony', __DIR__.'/framework');
+ *
+ * // activate the autoloader
+ * $loader->register();
+ *
+ * // to enable searching the include path (eg. for PEAR packages)
+ * $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier
+ * @author Jordi Boggiano
+ * @see https://www.php-fig.org/psr/psr-0/
+ * @see https://www.php-fig.org/psr/psr-4/
+ */
+class ClassLoader
+{
+ /** @var \Closure(string):void */
+ private static $includeFile;
+
+ /** @var string|null */
+ private $vendorDir;
+
+ // PSR-4
+ /**
+ * @var array>
+ */
+ private $prefixLengthsPsr4 = array();
+ /**
+ * @var array>
+ */
+ private $prefixDirsPsr4 = array();
+ /**
+ * @var list
+ */
+ private $fallbackDirsPsr4 = array();
+
+ // PSR-0
+ /**
+ * List of PSR-0 prefixes
+ *
+ * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
+ *
+ * @var array>>
+ */
+ private $prefixesPsr0 = array();
+ /**
+ * @var list
+ */
+ private $fallbackDirsPsr0 = array();
+
+ /** @var bool */
+ private $useIncludePath = false;
+
+ /**
+ * @var array
+ */
+ private $classMap = array();
+
+ /** @var bool */
+ private $classMapAuthoritative = false;
+
+ /**
+ * @var array
+ */
+ private $missingClasses = array();
+
+ /** @var string|null */
+ private $apcuPrefix;
+
+ /**
+ * @var array
+ */
+ private static $registeredLoaders = array();
+
+ /**
+ * @param string|null $vendorDir
+ */
+ public function __construct($vendorDir = null)
+ {
+ $this->vendorDir = $vendorDir;
+ self::initializeIncludeClosure();
+ }
+
+ /**
+ * @return array>
+ */
+ public function getPrefixes()
+ {
+ if (!empty($this->prefixesPsr0)) {
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
+ }
+
+ return array();
+ }
+
+ /**
+ * @return array>
+ */
+ public function getPrefixesPsr4()
+ {
+ return $this->prefixDirsPsr4;
+ }
+
+ /**
+ * @return list
+ */
+ public function getFallbackDirs()
+ {
+ return $this->fallbackDirsPsr0;
+ }
+
+ /**
+ * @return list
+ */
+ public function getFallbackDirsPsr4()
+ {
+ return $this->fallbackDirsPsr4;
+ }
+
+ /**
+ * @return array Array of classname => path
+ */
+ public function getClassMap()
+ {
+ return $this->classMap;
+ }
+
+ /**
+ * @param array $classMap Class to filename map
+ *
+ * @return void
+ */
+ public function addClassMap(array $classMap)
+ {
+ if ($this->classMap) {
+ $this->classMap = array_merge($this->classMap, $classMap);
+ } else {
+ $this->classMap = $classMap;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix, either
+ * appending or prepending to the ones previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param list|string $paths The PSR-0 root directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @return void
+ */
+ public function add($prefix, $paths, $prepend = false)
+ {
+ $paths = (array) $paths;
+ if (!$prefix) {
+ if ($prepend) {
+ $this->fallbackDirsPsr0 = array_merge(
+ $paths,
+ $this->fallbackDirsPsr0
+ );
+ } else {
+ $this->fallbackDirsPsr0 = array_merge(
+ $this->fallbackDirsPsr0,
+ $paths
+ );
+ }
+
+ return;
+ }
+
+ $first = $prefix[0];
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
+ $this->prefixesPsr0[$first][$prefix] = $paths;
+
+ return;
+ }
+ if ($prepend) {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $paths,
+ $this->prefixesPsr0[$first][$prefix]
+ );
+ } else {
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
+ $this->prefixesPsr0[$first][$prefix],
+ $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace, either
+ * appending or prepending to the ones previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list|string $paths The PSR-4 base directories
+ * @param bool $prepend Whether to prepend the directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function addPsr4($prefix, $paths, $prepend = false)
+ {
+ $paths = (array) $paths;
+ if (!$prefix) {
+ // Register directories for the root namespace.
+ if ($prepend) {
+ $this->fallbackDirsPsr4 = array_merge(
+ $paths,
+ $this->fallbackDirsPsr4
+ );
+ } else {
+ $this->fallbackDirsPsr4 = array_merge(
+ $this->fallbackDirsPsr4,
+ $paths
+ );
+ }
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+ // Register directories for a new namespace.
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = $paths;
+ } elseif ($prepend) {
+ // Prepend directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $paths,
+ $this->prefixDirsPsr4[$prefix]
+ );
+ } else {
+ // Append directories for an already registered namespace.
+ $this->prefixDirsPsr4[$prefix] = array_merge(
+ $this->prefixDirsPsr4[$prefix],
+ $paths
+ );
+ }
+ }
+
+ /**
+ * Registers a set of PSR-0 directories for a given prefix,
+ * replacing any others previously set for this prefix.
+ *
+ * @param string $prefix The prefix
+ * @param list|string $paths The PSR-0 base directories
+ *
+ * @return void
+ */
+ public function set($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr0 = (array) $paths;
+ } else {
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Registers a set of PSR-4 directories for a given namespace,
+ * replacing any others previously set for this namespace.
+ *
+ * @param string $prefix The prefix/namespace, with trailing '\\'
+ * @param list|string $paths The PSR-4 base directories
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return void
+ */
+ public function setPsr4($prefix, $paths)
+ {
+ if (!$prefix) {
+ $this->fallbackDirsPsr4 = (array) $paths;
+ } else {
+ $length = strlen($prefix);
+ if ('\\' !== $prefix[$length - 1]) {
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+ }
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
+ }
+ }
+
+ /**
+ * Turns on searching the include path for class files.
+ *
+ * @param bool $useIncludePath
+ *
+ * @return void
+ */
+ public function setUseIncludePath($useIncludePath)
+ {
+ $this->useIncludePath = $useIncludePath;
+ }
+
+ /**
+ * Can be used to check if the autoloader uses the include path to check
+ * for classes.
+ *
+ * @return bool
+ */
+ public function getUseIncludePath()
+ {
+ return $this->useIncludePath;
+ }
+
+ /**
+ * Turns off searching the prefix and fallback directories for classes
+ * that have not been registered with the class map.
+ *
+ * @param bool $classMapAuthoritative
+ *
+ * @return void
+ */
+ public function setClassMapAuthoritative($classMapAuthoritative)
+ {
+ $this->classMapAuthoritative = $classMapAuthoritative;
+ }
+
+ /**
+ * Should class lookup fail if not found in the current class map?
+ *
+ * @return bool
+ */
+ public function isClassMapAuthoritative()
+ {
+ return $this->classMapAuthoritative;
+ }
+
+ /**
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
+ *
+ * @param string|null $apcuPrefix
+ *
+ * @return void
+ */
+ public function setApcuPrefix($apcuPrefix)
+ {
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
+ }
+
+ /**
+ * The APCu prefix in use, or null if APCu caching is not enabled.
+ *
+ * @return string|null
+ */
+ public function getApcuPrefix()
+ {
+ return $this->apcuPrefix;
+ }
+
+ /**
+ * Registers this instance as an autoloader.
+ *
+ * @param bool $prepend Whether to prepend the autoloader or not
+ *
+ * @return void
+ */
+ public function register($prepend = false)
+ {
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+
+ if (null === $this->vendorDir) {
+ return;
+ }
+
+ if ($prepend) {
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
+ } else {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ self::$registeredLoaders[$this->vendorDir] = $this;
+ }
+ }
+
+ /**
+ * Unregisters this instance as an autoloader.
+ *
+ * @return void
+ */
+ public function unregister()
+ {
+ spl_autoload_unregister(array($this, 'loadClass'));
+
+ if (null !== $this->vendorDir) {
+ unset(self::$registeredLoaders[$this->vendorDir]);
+ }
+ }
+
+ /**
+ * Loads the given class or interface.
+ *
+ * @param string $class The name of the class
+ * @return true|null True if loaded, null otherwise
+ */
+ public function loadClass($class)
+ {
+ if ($file = $this->findFile($class)) {
+ $includeFile = self::$includeFile;
+ $includeFile($file);
+
+ return true;
+ }
+
+ return null;
+ }
+
+ /**
+ * Finds the path to the file where the class is defined.
+ *
+ * @param string $class The name of the class
+ *
+ * @return string|false The path if found, false otherwise
+ */
+ public function findFile($class)
+ {
+ // class map lookup
+ if (isset($this->classMap[$class])) {
+ return $this->classMap[$class];
+ }
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
+ return false;
+ }
+ if (null !== $this->apcuPrefix) {
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
+ if ($hit) {
+ return $file;
+ }
+ }
+
+ $file = $this->findFileWithExtension($class, '.php');
+
+ // Search for Hack files if we are running on HHVM
+ if (false === $file && defined('HHVM_VERSION')) {
+ $file = $this->findFileWithExtension($class, '.hh');
+ }
+
+ if (null !== $this->apcuPrefix) {
+ apcu_add($this->apcuPrefix.$class, $file);
+ }
+
+ if (false === $file) {
+ // Remember that this class does not exist.
+ $this->missingClasses[$class] = true;
+ }
+
+ return $file;
+ }
+
+ /**
+ * Returns the currently registered loaders keyed by their corresponding vendor directories.
+ *
+ * @return array
+ */
+ public static function getRegisteredLoaders()
+ {
+ return self::$registeredLoaders;
+ }
+
+ /**
+ * @param string $class
+ * @param string $ext
+ * @return string|false
+ */
+ private function findFileWithExtension($class, $ext)
+ {
+ // PSR-4 lookup
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+ $first = $class[0];
+ if (isset($this->prefixLengthsPsr4[$first])) {
+ $subPath = $class;
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
+ $subPath = substr($subPath, 0, $lastPos);
+ $search = $subPath . '\\';
+ if (isset($this->prefixDirsPsr4[$search])) {
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
+ if (file_exists($file = $dir . $pathEnd)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-4 fallback dirs
+ foreach ($this->fallbackDirsPsr4 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 lookup
+ if (false !== $pos = strrpos($class, '\\')) {
+ // namespaced class name
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+ } else {
+ // PEAR-like class name
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+ }
+
+ if (isset($this->prefixesPsr0[$first])) {
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+ if (0 === strpos($class, $prefix)) {
+ foreach ($dirs as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+ }
+ }
+ }
+
+ // PSR-0 fallback dirs
+ foreach ($this->fallbackDirsPsr0 as $dir) {
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+ return $file;
+ }
+ }
+
+ // PSR-0 include paths.
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+ return $file;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return void
+ */
+ private static function initializeIncludeClosure()
+ {
+ if (self::$includeFile !== null) {
+ return;
+ }
+
+ /**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ *
+ * @param string $file
+ * @return void
+ */
+ self::$includeFile = \Closure::bind(static function($file) {
+ include $file;
+ }, null, null);
+ }
+}
diff --git a/vendor/composer/InstalledVersions.php b/vendor/composer/InstalledVersions.php
new file mode 100644
index 0000000..51e734a
--- /dev/null
+++ b/vendor/composer/InstalledVersions.php
@@ -0,0 +1,359 @@
+
+ * Jordi Boggiano
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer;
+
+use Composer\Autoload\ClassLoader;
+use Composer\Semver\VersionParser;
+
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require its presence, you can require `composer-runtime-api ^2.0`
+ *
+ * @final
+ */
+class InstalledVersions
+{
+ /**
+ * @var mixed[]|null
+ * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null
+ */
+ private static $installed;
+
+ /**
+ * @var bool|null
+ */
+ private static $canGetVendors;
+
+ /**
+ * @var array[]
+ * @psalm-var array}>
+ */
+ private static $installedByVendor = array();
+
+ /**
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
+ *
+ * @return string[]
+ * @psalm-return list
+ */
+ public static function getInstalledPackages()
+ {
+ $packages = array();
+ foreach (self::getInstalled() as $installed) {
+ $packages[] = array_keys($installed['versions']);
+ }
+
+ if (1 === \count($packages)) {
+ return $packages[0];
+ }
+
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+ }
+
+ /**
+ * Returns a list of all package names with a specific type e.g. 'library'
+ *
+ * @param string $type
+ * @return string[]
+ * @psalm-return list
+ */
+ public static function getInstalledPackagesByType($type)
+ {
+ $packagesByType = array();
+
+ foreach (self::getInstalled() as $installed) {
+ foreach ($installed['versions'] as $name => $package) {
+ if (isset($package['type']) && $package['type'] === $type) {
+ $packagesByType[] = $name;
+ }
+ }
+ }
+
+ return $packagesByType;
+ }
+
+ /**
+ * Checks whether the given package is installed
+ *
+ * This also returns true if the package name is provided or replaced by another package
+ *
+ * @param string $packageName
+ * @param bool $includeDevRequirements
+ * @return bool
+ */
+ public static function isInstalled($packageName, $includeDevRequirements = true)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (isset($installed['versions'][$packageName])) {
+ return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks whether the given package satisfies a version constraint
+ *
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+ *
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+ *
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
+ * @param string $packageName
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+ * @return bool
+ */
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
+ {
+ $constraint = $parser->parseConstraints((string) $constraint);
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+ return $provided->matches($constraint);
+ }
+
+ /**
+ * Returns a version constraint representing all the range(s) which are installed for a given package
+ *
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+ * whether a given version of a package is installed, and not just whether it exists
+ *
+ * @param string $packageName
+ * @return string Version constraint usable with composer/semver
+ */
+ public static function getVersionRanges($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ $ranges = array();
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+ }
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+ }
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+ }
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+ }
+
+ return implode(' || ', $ranges);
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+ */
+ public static function getPrettyVersion($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['pretty_version'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+ */
+ public static function getReference($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ if (!isset($installed['versions'][$packageName]['reference'])) {
+ return null;
+ }
+
+ return $installed['versions'][$packageName]['reference'];
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @param string $packageName
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+ */
+ public static function getInstallPath($packageName)
+ {
+ foreach (self::getInstalled() as $installed) {
+ if (!isset($installed['versions'][$packageName])) {
+ continue;
+ }
+
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+ }
+
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+ }
+
+ /**
+ * @return array
+ * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
+ */
+ public static function getRootPackage()
+ {
+ $installed = self::getInstalled();
+
+ return $installed[0]['root'];
+ }
+
+ /**
+ * Returns the raw installed.php data for custom implementations
+ *
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+ * @return array[]
+ * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}
+ */
+ public static function getRawData()
+ {
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ self::$installed = include __DIR__ . '/installed.php';
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ return self::$installed;
+ }
+
+ /**
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
+ *
+ * @return array[]
+ * @psalm-return list}>
+ */
+ public static function getAllRawData()
+ {
+ return self::getInstalled();
+ }
+
+ /**
+ * Lets you reload the static array from another file
+ *
+ * This is only useful for complex integrations in which a project needs to use
+ * this class but then also needs to execute another project's autoloader in process,
+ * and wants to ensure both projects have access to their version of installed.php.
+ *
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
+ * the data it needs from this class, then call reload() with
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+ * the project in which it runs can then also use this class safely, without
+ * interference between PHPUnit's dependencies and the project's dependencies.
+ *
+ * @param array[] $data A vendor/composer/installed.php data set
+ * @return void
+ *
+ * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data
+ */
+ public static function reload($data)
+ {
+ self::$installed = $data;
+ self::$installedByVendor = array();
+ }
+
+ /**
+ * @return array[]
+ * @psalm-return list}>
+ */
+ private static function getInstalled()
+ {
+ if (null === self::$canGetVendors) {
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+ }
+
+ $installed = array();
+
+ if (self::$canGetVendors) {
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+ if (isset(self::$installedByVendor[$vendorDir])) {
+ $installed[] = self::$installedByVendor[$vendorDir];
+ } elseif (is_file($vendorDir.'/composer/installed.php')) {
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
+ $required = require $vendorDir.'/composer/installed.php';
+ $installed[] = self::$installedByVendor[$vendorDir] = $required;
+ if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+ self::$installed = $installed[count($installed) - 1];
+ }
+ }
+ }
+ }
+
+ if (null === self::$installed) {
+ // only require the installed.php file if this file is loaded from its dumped location,
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+ if (substr(__DIR__, -8, 1) !== 'C') {
+ /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */
+ $required = require __DIR__ . '/installed.php';
+ self::$installed = $required;
+ } else {
+ self::$installed = array();
+ }
+ }
+
+ if (self::$installed !== array()) {
+ $installed[] = self::$installed;
+ }
+
+ return $installed;
+ }
+}
diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE
new file mode 100644
index 0000000..f27399a
--- /dev/null
+++ b/vendor/composer/LICENSE
@@ -0,0 +1,21 @@
+
+Copyright (c) Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
new file mode 100644
index 0000000..ea26adb
--- /dev/null
+++ b/vendor/composer/autoload_classmap.php
@@ -0,0 +1,35 @@
+ $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
+ 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
+ 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+ 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
+ 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+ 'XMLSchema' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_base' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_client' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_client_mime' => $vendorDir . '/econea/nusoap/src/nusoapmime.php',
+ 'nusoap_fault' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_parser' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_server' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_server_mime' => $vendorDir . '/econea/nusoap/src/nusoapmime.php',
+ 'nusoap_wsdlcache' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_xmlschema' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'nusoapservermime' => $vendorDir . '/econea/nusoap/src/nusoapmime.php',
+ 'soap_fault' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'soap_parser' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'soap_server' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'soap_transport_http' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'soapclient' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'soapclientmime' => $vendorDir . '/econea/nusoap/src/nusoapmime.php',
+ 'soapval' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'wsdl' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+ 'wsdlcache' => $vendorDir . '/econea/nusoap/src/nusoap.php',
+);
diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php
new file mode 100644
index 0000000..7ff36b4
--- /dev/null
+++ b/vendor/composer/autoload_files.php
@@ -0,0 +1,12 @@
+ $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
+ 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
+);
diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php
new file mode 100644
index 0000000..15a2ff3
--- /dev/null
+++ b/vendor/composer/autoload_namespaces.php
@@ -0,0 +1,9 @@
+ array($vendorDir . '/symfony/polyfill-php80'),
+ 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
+ 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
+ 'SeinopSys\\' => array($vendorDir . '/seinopsys/postgresql-database-class/src'),
+ 'PhpOption\\' => array($vendorDir . '/phpoption/phpoption/src/PhpOption'),
+ 'GrahamCampbell\\ResultType\\' => array($vendorDir . '/graham-campbell/result-type/src'),
+ 'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
+);
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
new file mode 100644
index 0000000..9f1466d
--- /dev/null
+++ b/vendor/composer/autoload_real.php
@@ -0,0 +1,50 @@
+register(true);
+
+ $filesToLoad = \Composer\Autoload\ComposerStaticInit0ce6dc0c7b6fc3438416a20ddd0b5912::$files;
+ $requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+
+ require $file;
+ }
+ }, null, null);
+ foreach ($filesToLoad as $fileIdentifier => $file) {
+ $requireFile($fileIdentifier, $file);
+ }
+
+ return $loader;
+ }
+}
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
new file mode 100644
index 0000000..0624ac3
--- /dev/null
+++ b/vendor/composer/autoload_static.php
@@ -0,0 +1,106 @@
+ __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
+ '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
+ 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
+ );
+
+ public static $prefixLengthsPsr4 = array (
+ 'S' =>
+ array (
+ 'Symfony\\Polyfill\\Php80\\' => 23,
+ 'Symfony\\Polyfill\\Mbstring\\' => 26,
+ 'Symfony\\Polyfill\\Ctype\\' => 23,
+ 'SeinopSys\\' => 10,
+ ),
+ 'P' =>
+ array (
+ 'PhpOption\\' => 10,
+ ),
+ 'G' =>
+ array (
+ 'GrahamCampbell\\ResultType\\' => 26,
+ ),
+ 'D' =>
+ array (
+ 'Dotenv\\' => 7,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'Symfony\\Polyfill\\Php80\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
+ ),
+ 'Symfony\\Polyfill\\Mbstring\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
+ ),
+ 'Symfony\\Polyfill\\Ctype\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
+ ),
+ 'SeinopSys\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/seinopsys/postgresql-database-class/src',
+ ),
+ 'PhpOption\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/phpoption/phpoption/src/PhpOption',
+ ),
+ 'GrahamCampbell\\ResultType\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/graham-campbell/result-type/src',
+ ),
+ 'Dotenv\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/vlucas/phpdotenv/src',
+ ),
+ );
+
+ public static $classMap = array (
+ 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
+ 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
+ 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
+ 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
+ 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
+ 'XMLSchema' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_base' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_client' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_client_mime' => __DIR__ . '/..' . '/econea/nusoap/src/nusoapmime.php',
+ 'nusoap_fault' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_parser' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_server' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_server_mime' => __DIR__ . '/..' . '/econea/nusoap/src/nusoapmime.php',
+ 'nusoap_wsdlcache' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoap_xmlschema' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'nusoapservermime' => __DIR__ . '/..' . '/econea/nusoap/src/nusoapmime.php',
+ 'soap_fault' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'soap_parser' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'soap_server' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'soap_transport_http' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'soapclient' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'soapclientmime' => __DIR__ . '/..' . '/econea/nusoap/src/nusoapmime.php',
+ 'soapval' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'wsdl' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ 'wsdlcache' => __DIR__ . '/..' . '/econea/nusoap/src/nusoap.php',
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInit0ce6dc0c7b6fc3438416a20ddd0b5912::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInit0ce6dc0c7b6fc3438416a20ddd0b5912::$prefixDirsPsr4;
+ $loader->classMap = ComposerStaticInit0ce6dc0c7b6fc3438416a20ddd0b5912::$classMap;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
new file mode 100644
index 0000000..bef2878
--- /dev/null
+++ b/vendor/composer/installed.json
@@ -0,0 +1,605 @@
+{
+ "packages": [
+ {
+ "name": "econea/nusoap",
+ "version": "v0.9.17",
+ "version_normalized": "0.9.17.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/f00b4r/nusoap.git",
+ "reference": "ac2322f37808ecb1a2b84ed469cba9c51648eb8d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/f00b4r/nusoap/zipball/ac2322f37808ecb1a2b84ed469cba9c51648eb8d",
+ "reference": "ac2322f37808ecb1a2b84ed469cba9c51648eb8d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-curl": "*",
+ "ext-json": "*",
+ "ext-xml": "*",
+ "ext-zlib": "*",
+ "php": ">=5.4"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-parallel-lint": "~1.2.0"
+ },
+ "time": "2024-01-25T09:08:59+00:00",
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "0.10.x-dev"
+ }
+ },
+ "installation-source": "source",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-2.1-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Milan Felix Šulc",
+ "homepage": "https://f3l1x.io"
+ }
+ ],
+ "description": "Fixed NuSOAP for PHP 5.4 - 8.2",
+ "homepage": "https://github.com/pwnlabs/nusoap",
+ "keywords": [
+ "client",
+ "http",
+ "nusoap",
+ "php",
+ "soap",
+ "transport",
+ "xml"
+ ],
+ "support": {
+ "issues": "https://github.com/f00b4r/nusoap/issues",
+ "source": "https://github.com/f00b4r/nusoap/tree/v0.9.17"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/f3l1x",
+ "type": "github"
+ }
+ ],
+ "install-path": "../econea/nusoap"
+ },
+ {
+ "name": "graham-campbell/result-type",
+ "version": "v1.1.3",
+ "version_normalized": "1.1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/GrahamCampbell/Result-Type.git",
+ "reference": "3ba905c11371512af9d9bdd27d99b782216b6945"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945",
+ "reference": "3ba905c11371512af9d9bdd27d99b782216b6945",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "phpoption/phpoption": "^1.9.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
+ },
+ "time": "2024-07-20T21:45:45+00:00",
+ "type": "library",
+ "installation-source": "source",
+ "autoload": {
+ "psr-4": {
+ "GrahamCampbell\\ResultType\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ }
+ ],
+ "description": "An Implementation Of The Result Type",
+ "keywords": [
+ "Graham Campbell",
+ "GrahamCampbell",
+ "Result Type",
+ "Result-Type",
+ "result"
+ ],
+ "support": {
+ "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
+ "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../graham-campbell/result-type"
+ },
+ {
+ "name": "phpoption/phpoption",
+ "version": "1.9.3",
+ "version_normalized": "1.9.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/schmittjoh/php-option.git",
+ "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54",
+ "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
+ },
+ "time": "2024-07-20T21:41:07+00:00",
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ },
+ "branch-alias": {
+ "dev-master": "1.9-dev"
+ }
+ },
+ "installation-source": "source",
+ "autoload": {
+ "psr-4": {
+ "PhpOption\\": "src/PhpOption/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Johannes M. Schmitt",
+ "email": "schmittjoh@gmail.com",
+ "homepage": "https://github.com/schmittjoh"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ }
+ ],
+ "description": "Option Type for PHP",
+ "keywords": [
+ "language",
+ "option",
+ "php",
+ "type"
+ ],
+ "support": {
+ "issues": "https://github.com/schmittjoh/php-option/issues",
+ "source": "https://github.com/schmittjoh/php-option/tree/1.9.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../phpoption/phpoption"
+ },
+ {
+ "name": "seinopsys/postgresql-database-class",
+ "version": "v3.1.1",
+ "version_normalized": "3.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/SeinopSys/PHP-PostgreSQL-Database-Class.git",
+ "reference": "47a648fdb67c2fc27e8ff35091c8e36cd95596e9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/SeinopSys/PHP-PostgreSQL-Database-Class/zipball/47a648fdb67c2fc27e8ff35091c8e36cd95596e9",
+ "reference": "47a648fdb67c2fc27e8ff35091c8e36cd95596e9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-pdo": "*",
+ "ext-pdo_pgsql": "*",
+ "php": ">=5.4"
+ },
+ "require-dev": {
+ "squizlabs/php_codesniffer": "3.*"
+ },
+ "time": "2019-05-26T17:41:40+00:00",
+ "type": "library",
+ "installation-source": "source",
+ "autoload": {
+ "psr-4": {
+ "SeinopSys\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "SeinopSys",
+ "email": "seinopsys@gmail.com",
+ "homepage": "https://github.com/SeinopSys",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP wrapper class for PDO-based interaction with PostgreSQL databases, heavily based on ThingEngineer's MysqliDb class",
+ "support": {
+ "issues": "https://github.com/SeinopSys/PHP-PostgreSQL-Database-Class/issues",
+ "source": "https://github.com/SeinopSys/PHP-PostgreSQL-Database-Class/tree/master"
+ },
+ "install-path": "../seinopsys/postgresql-database-class"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.30.0",
+ "version_normalized": "1.30.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "0424dff1c58f028c451efff2045f5d92410bd540"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/0424dff1c58f028c451efff2045f5d92410bd540",
+ "reference": "0424dff1c58f028c451efff2045f5d92410bd540",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "time": "2024-05-31T15:07:36+00:00",
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "installation-source": "source",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/polyfill-ctype"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.30.0",
+ "version_normalized": "1.30.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c",
+ "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "time": "2024-06-19T12:30:46+00:00",
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "installation-source": "source",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/polyfill-mbstring"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.30.0",
+ "version_normalized": "1.30.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "77fa7995ac1b21ab60769b7323d600a991a90433"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433",
+ "reference": "77fa7995ac1b21ab60769b7323d600a991a90433",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "time": "2024-05-31T15:07:36+00:00",
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "installation-source": "source",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../symfony/polyfill-php80"
+ },
+ {
+ "name": "vlucas/phpdotenv",
+ "version": "v5.6.1",
+ "version_normalized": "5.6.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/vlucas/phpdotenv.git",
+ "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2",
+ "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2",
+ "shasum": ""
+ },
+ "require": {
+ "ext-pcre": "*",
+ "graham-campbell/result-type": "^1.1.3",
+ "php": "^7.2.5 || ^8.0",
+ "phpoption/phpoption": "^1.9.3",
+ "symfony/polyfill-ctype": "^1.24",
+ "symfony/polyfill-mbstring": "^1.24",
+ "symfony/polyfill-php80": "^1.24"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-filter": "*",
+ "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
+ },
+ "suggest": {
+ "ext-filter": "Required to use the boolean validator."
+ },
+ "time": "2024-07-20T21:52:34+00:00",
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ },
+ "branch-alias": {
+ "dev-master": "5.6-dev"
+ }
+ },
+ "installation-source": "source",
+ "autoload": {
+ "psr-4": {
+ "Dotenv\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Vance Lucas",
+ "email": "vance@vancelucas.com",
+ "homepage": "https://github.com/vlucas"
+ }
+ ],
+ "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
+ "keywords": [
+ "dotenv",
+ "env",
+ "environment"
+ ],
+ "support": {
+ "issues": "https://github.com/vlucas/phpdotenv/issues",
+ "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
+ "type": "tidelift"
+ }
+ ],
+ "install-path": "../vlucas/phpdotenv"
+ }
+ ],
+ "dev": true,
+ "dev-package-names": []
+}
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
new file mode 100644
index 0000000..89a108f
--- /dev/null
+++ b/vendor/composer/installed.php
@@ -0,0 +1,95 @@
+ array(
+ 'name' => '__root__',
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'reference' => NULL,
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../',
+ 'aliases' => array(),
+ 'dev' => true,
+ ),
+ 'versions' => array(
+ '__root__' => array(
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'reference' => NULL,
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../../',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'econea/nusoap' => array(
+ 'pretty_version' => 'v0.9.17',
+ 'version' => '0.9.17.0',
+ 'reference' => 'ac2322f37808ecb1a2b84ed469cba9c51648eb8d',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../econea/nusoap',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'graham-campbell/result-type' => array(
+ 'pretty_version' => 'v1.1.3',
+ 'version' => '1.1.3.0',
+ 'reference' => '3ba905c11371512af9d9bdd27d99b782216b6945',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../graham-campbell/result-type',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'phpoption/phpoption' => array(
+ 'pretty_version' => '1.9.3',
+ 'version' => '1.9.3.0',
+ 'reference' => 'e3fac8b24f56113f7cb96af14958c0dd16330f54',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../phpoption/phpoption',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'seinopsys/postgresql-database-class' => array(
+ 'pretty_version' => 'v3.1.1',
+ 'version' => '3.1.1.0',
+ 'reference' => '47a648fdb67c2fc27e8ff35091c8e36cd95596e9',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../seinopsys/postgresql-database-class',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'symfony/polyfill-ctype' => array(
+ 'pretty_version' => 'v1.30.0',
+ 'version' => '1.30.0.0',
+ 'reference' => '0424dff1c58f028c451efff2045f5d92410bd540',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'symfony/polyfill-mbstring' => array(
+ 'pretty_version' => 'v1.30.0',
+ 'version' => '1.30.0.0',
+ 'reference' => 'fd22ab50000ef01661e2a31d850ebaa297f8e03c',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'symfony/polyfill-php80' => array(
+ 'pretty_version' => 'v1.30.0',
+ 'version' => '1.30.0.0',
+ 'reference' => '77fa7995ac1b21ab60769b7323d600a991a90433',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ 'vlucas/phpdotenv' => array(
+ 'pretty_version' => 'v5.6.1',
+ 'version' => '5.6.1.0',
+ 'reference' => 'a59a13791077fe3d44f90e7133eb68e7d22eaff2',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../vlucas/phpdotenv',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
+ ),
+);
diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php
new file mode 100644
index 0000000..a8b98d5
--- /dev/null
+++ b/vendor/composer/platform_check.php
@@ -0,0 +1,26 @@
+= 70205)) {
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.5". You are running ' . PHP_VERSION . '.';
+}
+
+if ($issues) {
+ if (!headers_sent()) {
+ header('HTTP/1.1 500 Internal Server Error');
+ }
+ if (!ini_get('display_errors')) {
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
+ fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
+ } elseif (!headers_sent()) {
+ echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
+ }
+ }
+ trigger_error(
+ 'Composer detected issues in your platform: ' . implode(' ', $issues),
+ E_USER_ERROR
+ );
+}
diff --git a/vendor/econea/nusoap b/vendor/econea/nusoap
new file mode 160000
index 0000000..ac2322f
--- /dev/null
+++ b/vendor/econea/nusoap
@@ -0,0 +1 @@
+Subproject commit ac2322f37808ecb1a2b84ed469cba9c51648eb8d
diff --git a/vendor/graham-campbell/result-type b/vendor/graham-campbell/result-type
new file mode 160000
index 0000000..3ba905c
--- /dev/null
+++ b/vendor/graham-campbell/result-type
@@ -0,0 +1 @@
+Subproject commit 3ba905c11371512af9d9bdd27d99b782216b6945
diff --git a/vendor/phpoption/phpoption b/vendor/phpoption/phpoption
new file mode 160000
index 0000000..e3fac8b
--- /dev/null
+++ b/vendor/phpoption/phpoption
@@ -0,0 +1 @@
+Subproject commit e3fac8b24f56113f7cb96af14958c0dd16330f54
diff --git a/vendor/seinopsys/postgresql-database-class b/vendor/seinopsys/postgresql-database-class
new file mode 160000
index 0000000..47a648f
--- /dev/null
+++ b/vendor/seinopsys/postgresql-database-class
@@ -0,0 +1 @@
+Subproject commit 47a648fdb67c2fc27e8ff35091c8e36cd95596e9
diff --git a/vendor/symfony/polyfill-ctype b/vendor/symfony/polyfill-ctype
new file mode 160000
index 0000000..0424dff
--- /dev/null
+++ b/vendor/symfony/polyfill-ctype
@@ -0,0 +1 @@
+Subproject commit 0424dff1c58f028c451efff2045f5d92410bd540
diff --git a/vendor/symfony/polyfill-mbstring b/vendor/symfony/polyfill-mbstring
new file mode 160000
index 0000000..fd22ab5
--- /dev/null
+++ b/vendor/symfony/polyfill-mbstring
@@ -0,0 +1 @@
+Subproject commit fd22ab50000ef01661e2a31d850ebaa297f8e03c
diff --git a/vendor/symfony/polyfill-php80 b/vendor/symfony/polyfill-php80
new file mode 160000
index 0000000..77fa799
--- /dev/null
+++ b/vendor/symfony/polyfill-php80
@@ -0,0 +1 @@
+Subproject commit 77fa7995ac1b21ab60769b7323d600a991a90433
diff --git a/vendor/vlucas/phpdotenv b/vendor/vlucas/phpdotenv
new file mode 160000
index 0000000..a59a137
--- /dev/null
+++ b/vendor/vlucas/phpdotenv
@@ -0,0 +1 @@
+Subproject commit a59a13791077fe3d44f90e7133eb68e7d22eaff2