HEX
Server: Apache
System: Linux p3plzcpnl506847.prod.phx3.secureserver.net 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: slfopp7cb1df (5698090)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: //home/slfopp7cb1df/www/sitepacket.com/system/app/Views/e_invoice_templates/modal_form.php
<?php echo form_open(get_uri("e_invoice_templates/save"), array("id" => "e-invoice-template-form", "class" => "general-form bg-white", "role" => "form")); ?>
<div class="modal-body clearfix">
    <div class="container-fluid">
        <div id="xml-validation-message">

        </div>
        <div class="row">
            <div class="col-md-9">
                <input type="hidden" name="id" value="<?php echo $model_info->id; ?>" />
                <div class="form-group">
                    <div class="row">
                        <div class="col-md-12">
                            <?php
                            echo form_input(array(
                                "id" => "title",
                                "name" => "title",
                                "value" => $model_info->title,
                                "class" => "form-control",
                                "placeholder" => app_lang('e_invoice_template_title'),
                                "autofocus" => true,
                                "data-rule-required" => true,
                                "data-msg-required" => app_lang("field_required"),
                            ));
                            ?>
                        </div>
                    </div>
                </div>

                <div class="undefined_variables text-danger"></div>

                <div id="xml-editor"></div>

                <div class="form-group d-none">
                    <div class="row">
                        <div class=" col-md-12">
                            <?php
                            echo form_textarea(array(
                                "name" => "template",
                                "id" => "e-invoice-template-textarea",
                                "value" => $model_info->template,
                                "class" => "form-control",
                                "placeholder" => app_lang('e_invoice_template'),
                                "data-rule-required" => true,
                                "data-msg-required" => app_lang("field_required"),
                            ));
                            ?>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-md-3 e-invoice-template-variables">
                <div class="form-group">
                    <div class="row">
                        <div class="col-md-12">
                            <ul class="list-group">
                                <li class="list-group-item">
                                    <div class="b-b pb15"><strong><?php echo app_lang("avilable_variables"); ?></strong></div>
                                </li>
                                <?php foreach ($available_variables as $group_name => $variables) { ?>
                                    <li class="list-group-item pb-0"><strong><?php echo app_lang($group_name); ?>:</strong></li>
                                    <ul>
                                        <?php foreach ($variables as $key => $variable) { ?>
                                            <?php if (is_array($variable)) { ?>
                                                <li class="list-group-item p-0 js-variable-tag clickable" data-bs-toggle="tooltip" data-bs-placement="left" title="<?php echo app_lang('copy'); ?>" data-title="<?php echo app_lang('copy'); ?>" data-after-click-title="<?php echo app_lang('copied'); ?>">{<?php echo $key; ?>}</li>
                                                <ul>
                                                    <?php foreach ($variable as $nested_variable) { ?>
                                                        <li class="list-group-item p-0 js-variable-tag clickable" data-bs-toggle="tooltip" data-bs-placement="left" title="<?php echo app_lang('copy'); ?>" data-title="<?php echo app_lang('copy'); ?>" data-after-click-title="<?php echo app_lang('copied'); ?>">{<?php echo $nested_variable; ?>}</li>
                                                    <?php } ?>
                                                </ul>
                                            <?php } else { ?>
                                                <li class="list-group-item p-0 js-variable-tag clickable" data-bs-toggle="tooltip" data-bs-placement="left" title="<?php echo app_lang('copy'); ?>" data-title="<?php echo app_lang('copy'); ?>" data-after-click-title="<?php echo app_lang('copied'); ?>">{<?php echo $variable; ?>}</li>
                                            <?php } ?>
                                        <?php } ?>
                                    </ul>
                                <?php } ?>
                                <li class="list-group-item">
                                    <div class="b-t pt15"><i data-feather="info" class="icon-16"></i> <?php echo app_lang('e_invoice_template_custom_field_variable_info'); ?></div>
                                </li>

                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<div class="modal-footer">
    <button type="button" class="btn btn-default" data-bs-dismiss="modal"><span data-feather="x" class="icon-16"></span> <?php echo app_lang('close'); ?></button>
    <button type="button" class="btn btn-danger spinning-btn validate-xml-btn"><span data-feather="arrow-right" class="icon-16"></span> <?php echo app_lang('validate_and_save'); ?></button>
    <button type="submit" class="btn btn-primary save-btn"><span data-feather="check-circle" class="icon-16"></span> <?php echo app_lang('save'); ?></button>
</div>
<?php echo form_close(); ?>

<script type="text/javascript">
    $(document).ready(function() {
        var editorInstance; // Global variable for CodeMirror instance

        setTimeout(function() {
            $("#title").focus();
            editorInstance = $("#xml-editor").xmlEditor(); // Initialize and store editor instance

            // editorInstance.on("change", function() {
            //     $(".validate-xml-btn").removeClass("d-none");
            //     //$(".save-btn").addClass("d-none");
            // });
        }, 200);

        $("#e-invoice-template-form").appForm({
            beforeAjaxSubmit: function(data) {
                $.each(data, function(index, obj) {
                    if (obj.name === "template") {
                        data[index]["value"] = editorInstance.getValue();
                    }
                });
            },
            onSuccess: function(result) {
                $("#e-invoice-templates-table").appTable({
                    newData: result.data,
                    dataId: result.id
                });
            }
        });



        $("#e-invoice-template-form .select2").select2();

        var modalHeight = $(window).height(),
            modalInnerHeight = modalHeight - 200;

        $(".e-invoice-template-variables").css("max-height", modalInnerHeight).css("overflow-y", "scroll");

        setTimeout(function() {
            $(".CodeMirror").css("min-height", modalInnerHeight - 65);
        }, 200);

        function getXMLValidationMessage(xmlString) {
            var parser = new DOMParser();
            var doc = parser.parseFromString(xmlString, "application/xml");
            var errorNode = doc.querySelector("parsererror");

            if (!errorNode) return "";

            // Parse the inner HTML into a DOM fragment
            const tempDoc = document.createElement("div");
            tempDoc.innerHTML = errorNode.innerHTML;

            // Replace all <h3> with <div>
            tempDoc.querySelectorAll("h3").forEach(h => {
                const div = document.createElement("div");
                div.innerHTML = h.innerHTML;
                h.replaceWith(div);
            });

            // Remove the last child (the "Below is a rendering..." message)
            if (tempDoc.lastElementChild) {
                tempDoc.removeChild(tempDoc.lastElementChild);
            }

            return tempDoc.innerHTML;
        }

        function getUnknownVariablesMessage(xmlContent) {
            var availableVariables = [],
                unknownVariables = [];

            // Collect all available variables from the page
            $(".js-variable-tag").each(function() {
                var variableText = $(this).text().trim();
                var variableName = variableText.replace(/[{}]/g, ""); // Remove { and }
                availableVariables.push(variableName);
            });

            // 1. Check variables inside { ... } tags
            xmlContent.replace(/\{([^{}]+)\}/g, function(match, contentInsideBraces) {
                // Skip special tags like {endif}, {else}, {elseif}, etc.
                if (/^(\/?if|else(if)?|endif)/.test(contentInsideBraces.trim())) {
                    return;
                }

                // Handle normal variables with optional filters
                var variableName = contentInsideBraces.split('|')[0].trim();

                if (
                    variableName &&
                    !availableVariables.includes(variableName) &&
                    !unknownVariables.includes(variableName)
                ) {
                    unknownVariables.push(variableName);
                }
            });

            // 2. Check variables inside {if $variable ...} conditions
            xmlContent.replace(/\{if\s+([^}]+)\}/g, function(match, conditionContent) {
                // Find all $variables inside condition
                var matches = conditionContent.match(/\$[a-zA-Z0-9_.]+/g);
                if (matches) {
                    matches.forEach(function(fullVar) {
                        var varName = fullVar.replace(/^\$/, ''); // Remove leading $

                        if (
                            varName &&
                            !availableVariables.includes(varName) &&
                            !unknownVariables.includes(varName)
                        ) {
                            unknownVariables.push(varName);
                        }
                    });
                }
            });

            if (unknownVariables.length > 0) {
                return `<div><span class="fw-bold"><?php echo app_lang('undefined_variables'); ?>: </span> ${unknownVariables.map(v => `{${v}}`).join(", ")}</div>`;
            }

            return "";
        }



        $(".validate-xml-btn").click(function() {
            var $button = $(this);

            if (!editorInstance) {
                return;
            }

            var xmlContent = editorInstance.getValue().trim(); // Get XML from CodeMirror

            setTimeout(function() {

                var alertHtml = getXMLValidationMessage(xmlContent);
                alertHtml = alertHtml += getUnknownVariablesMessage(xmlContent);

                if (alertHtml) {
                    appAlert.error(alertHtml, {
                        animate: false,
                        container: "#xml-validation-message"
                    });

                    $(".app-alert-message").css({
                        "max-width": "none"
                    });

                } else {
                    $button.addClass("d-none");
                    $(".save-btn").trigger("click");
                }

            }, 200);
        });

        $('[data-bs-toggle="tooltip"]').tooltip();
    });

    (function($) {
        $.fn.xmlEditor = function(options) {
            var settings = $.extend({
                xmlString: $("#e-invoice-template-textarea").val()
            }, options);

            var container = this;
            var textarea = $('<textarea class="xml-textarea"></textarea>').text(settings.xmlString);
            container.append(textarea);

            // Apply CodeMirror for syntax highlighting
            var editor = CodeMirror.fromTextArea(textarea[0], {
                mode: 'application/xml',
                lineNumbers: true,
                theme: 'material',
                indentUnit: 2,
                matchBrackets: true,
                autoCloseTags: true,
                viewportMargin: Infinity,
                refresh: true
            });

            return editor;
        };
    }(jQuery));
</script>