';
$html .= ($isBeta) ? ' ' : '';
return $html;
}
public static function backendUpdateWarning() {
$minSubVersion = self::getParamFromXMLFile('vfsubminversion', JPATH_ADMINISTRATOR . '/manifests/packages/pkg_vfbase.xml');
$subVersion = \VisformsAEF::getVersion(12);
return (!empty($subVersion) && !empty($minSubVersion) && (version_compare($subVersion, $minSubVersion, 'lt'))) ? '' . $customtext. '
';
}
}
if (self::customTextBottom == $position) {
if (($field->customtext != '') && (((isset($field->customtextposition)) && ($field->customtextposition == 2)) || !(isset($field->customtextposition)))) {
PluginHelper::importPlugin('content');
$customtext = HTMLHelper::_('content.prepare', $field->customtext);
return '' . $customtext. '
';
}
}
}
public static function getValidatorMessagesScript() {
if (!empty(static::$loaded[__METHOD__])) {
return;
}
$script = 'jQuery(document).ready(function () {
jQuery.extend(jQuery.validator.messages, {
required: "' . addslashes(Text::_('COM_VISFORMS_ENTER_REQUIRED')) . '",
remote: "Please fix this field.",
email: "' . addslashes(Text::_('COM_VISFORMS_ENTER_VALID_EMAIL')) . '",
url: "' . addslashes(Text::_('COM_VISFORMS_ENTER_VALID_URL')) . '",
date: "' . addslashes(Text::_('COM_VISFORMS_ENTER_VALID_DATE')) . '",
dateISO: "Please enter a valid date (ISO).",
number: "' . addslashes(Text::_('COM_VISFORMS_ENTER_VALID_NUMBER')) . '",
digits: "' . addslashes(Text::_('COM_VISMORMS_ENTER_VALID_DIGIT')) . '",
creditcard: "Please enter a valid credit card number.",
equalTo: "' . addslashes(Text::_('COM_VISFORMS_ENTER_CONFIRM')) . '",
maxlength: jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_MAXLENGTH')) . '"),
minlength: jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_MINLENGTH')) . '"),
rangelength: jQuery.validator.format("' . addslashes(Text::_('COM_VISMORMS_ENTER_VAILD_LENGTH')) . '"),
range: jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_RANGE')) . '"),
max: jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_MAX_VALUE')) . '"),
min: jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_ENTER_VAILD_MIN_VALUE')) . '"),
customvalidation: "' . addslashes(Text::_('COM_VISFORMS_INVALID_INPUT')) . '",
ispair: "' . addslashes(Text::_('COM_VISFORMS_ISPAIR_VALIDATION_FAILED_JS')) . '"
});
});';
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->addInlineScript($script, [], ['type' => 'module'], []);
static::$loaded[__METHOD__] = true;
}
public static function getValidatorMethodsScript() {
if (!empty(static::$loaded[__METHOD__])) {
return;
}
$script = 'jQuery(document).ready(function () {
jQuery.validator.addMethod("dateDMY", function (value, element) {
var check = false;
var re = /^(0[1-9]|[12][0-9]|3[01])[\.](0[1-9]|1[012])[\.]\d{4}$/;
if (re.test(value)) {
var adata = value.split(".");
var day = parseInt(adata[0], 10);
var month = parseInt(adata[1], 10);
var year = parseInt(adata[2], 10);
if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) {
check = false; // 31st of a month with 30 days
} else if (day >= 30 && month == 2) {
check = false; // February 30th or 31st
} else if (month == 2 && day == 29 && !(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
check = false; // February 29th outside a leap year
} else {
check = true; // Valid date
}
}
// the calender does not allow to clear values if it is required (js). So the required option in this validation is just a workaround fallback
if (value == "0000-00-00 00:00:00" && !jQuery(element).prop("required")) {
check = true;
}
return this.optional(element) || check;
});
jQuery.validator.addMethod("dateMDY", function (value, element) {
var check = false;
var re = /^(0[1-9]|1[012])[\/](0[1-9]|[12][0-9]|3[01])[\/]\d{4}$/;
if (re.test(value)) {
var adata = value.split("/");
var month = parseInt(adata[0], 10);
var day = parseInt(adata[1], 10);
var year = parseInt(adata[2], 10);
if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) {
check = false; // 31st of a month with 30 days
} else if (day >= 30 && month == 2) {
check = false; // February 30th or 31st
} else if (month == 2 && day == 29 && !(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
check = false; // February 29th outside a leap year
} else {
check = true; // Valid date
}
}
// the calender does not allow to clear values if it is required (js). So the required option in this validation is just a workaround fallback
if (value == "0000-00-00 00:00:00" && !jQuery(element).prop("required")) {
check = true;
}
return this.optional(element) || check;
});
jQuery.validator.addMethod("dateYMD", function (value, element) {
var check = false;
var re = /^\d{4}[\-](0[1-9]|1[012])[\-](0[1-9]|[12][0-9]|3[01])$/;
if (re.test(value)) {
var adata = value.split("-");
var year = parseInt(adata[0], 10);
var month = parseInt(adata[1], 10);
var day = parseInt(adata[2], 10);
if (day == 31 && (month == 4 || month == 6 || month == 9 || month == 11)) {
check = false; // 31st of a month with 30 days
} else if (day >= 30 && month == 2) {
check = false; // February 30th or 31st
} else if (month == 2 && day == 29 && !(year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
check = false; // February 29th outside a leap year
} else {
check = true; // Valid date
}
}
// the calender does not allow to clear values if it is required (js). So the required option in this validation is just a workaround fallback
if (value == "0000-00-00 00:00:00" && !jQuery(element).prop("required")) {
check = true;
}
return this.optional(element) || check;
});
jQuery.validator.addMethod("filesize", function (value, element, maxsize) {
var check = false;
if ((maxsize === 0) || ((!(element.files.length == 0)) && (element.files[0].size < maxsize)))
{
check = true;
}
return this.optional(element) || check;
});
jQuery.validator.addMethod("fileextension", function (value, element, allowedextension) {
var check = false;
allowedextension = allowedextension.replace(/\s/g, "");
allowedextension = allowedextension.split(",");
var fileext = jQuery(element).val().split(".").pop().toLowerCase();
if (jQuery.inArray(fileext, allowedextension) > -1)
{
check = true;
}
return this.optional(element) || check;
});
jQuery.validator.addMethod("customvalidation", function (value, element, re) {
return this.optional(element) || re.test(value);
});
jQuery.validator.addMethod("ispair", function (value, element, id) {
var latval = document.getElementById(id+"_lat").value;
var lngval = document.getElementById(id+"_lng").value;
// false if on field is empty and the other not
var check = ((latval === "" && lngval === "") || (latval !== "" && lngval !== ""));
var relatval = /^[-]?(([0-8]?[0-9])\.(\d+))|(90(\.0+)?)$/;
var relngval = /^[-]?((((1[0-7][0-9])|([0-9]?[0-9]))\.(\d+))|180(\.0+)?)$/;
check = (latval === "" || relatval.test(latval)) && check;
check = (lngval === "" || relngval.test(lngval)) && check;
return check;
});
jQuery.validator.addMethod("mindate", function(value, element, options) {
var check = false;
var minDate = "";
if (value) {
if (options.fromField) {
var fieldId = options.value;
var field = document.getElementById(fieldId);
if (!field) {
return true;
}
if (field.disabled) {
return true;
}
minDate = field.value;
if (!minDate) {
return true;
}
} else {
minDate = options.value;
}
var format, i = 0, fmt = {}, minDateFormat, j = 0, minDateFmt = {}, day;
format = (value.indexOf(".") > -1) ? "dd.mm.yyyy" : ((value.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });
minDateFormat = (minDate.indexOf(".") > -1) ? "dd.mm.yyyy" : ((minDate.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
minDateFormat.replace(/(yyyy|dd|mm)/g, function(part) { minDateFmt[part] = j++; });
var minDateParts = minDate.match(/(\d+)/g);
var valueParts = value.match(/(\d+)/g);
minDate = new Date(minDateParts[minDateFmt["yyyy"]], minDateParts[minDateFmt["mm"]]-1, minDateParts[minDateFmt["dd"]],0,0,0,0);
if (options.shift) {
var shift = options.shift;
day = minDate.getDate();
day = day + parseInt(shift);
minDate.setDate(day);
}
value = new Date(valueParts[fmt["yyyy"]], valueParts[fmt["mm"]]-1, valueParts[fmt["dd"]],0,0,0,0);
check = value >= minDate;
}
return this.optional(element) || check;
}, function(options, element) {
// validation message
if (options.fromField) {
var minDate = "";
var fieldId = options.value;
var field = document.getElementById(fieldId);
if (field) {
minDate = field.value;
}
} else {
minDate = options.value;
}
var format, minDateFormat, j = 0, minDateFmt = {}, day, month, year, valDate;
minDateFormat = (minDate.indexOf(".") > -1) ? "dd.mm.yyyy" : ((minDate.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
minDateFormat.replace(/(yyyy|dd|mm)/g, function(part) { minDateFmt[part] = j++; });
var minDateParts = minDate.match(/(\d+)/g);
minDate = new Date(minDateParts[minDateFmt["yyyy"]], minDateParts[minDateFmt["mm"]]-1, minDateParts[minDateFmt["dd"]],0,0,0,0);
if (options.shift) {
var shift = options.shift;
day = minDate.getDate();
day = day + parseInt(shift);
minDate.setDate(day);
}
format = options.format;
valDate = "";
day = minDate.getDate();
if (day < 10) {
day = "0" + day;
}
month = 1 + minDate.getMonth();
if (month < 10) {
month = "0" + month;
}
year = minDate.getFullYear();
switch (format) {
case "%Y-%m-%d" :
valDate = year + "-" + month + "-" + day;
break;
case "%m/%d/%Y" :
valDate = month + "/" + day + "/" + year;
break;
default :
valDate = day + "." + month + "." + year;
break;
}
return jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_MINDATE_VALIDATION_FAILED_JS')) . '", valDate);
});
jQuery.validator.addMethod("maxdate", function(value, element, options) {
var check = false;
var minDate = "";
if (value) {
if (options.fromField) {
var fieldId = options.value;
var field = document.getElementById(fieldId);
if (!field) {
return true;
}
if (field.disabled) {
return true;
}
minDate = field.value;
if (!minDate) {
return true;
}
} else {
minDate = options.value;
}
var format, i = 0, fmt = {}, minDateFormat, j = 0, minDateFmt = {}, day;
format = (value.indexOf(".") > -1) ? "dd.mm.yyyy" : ((value.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });
minDateFormat = (minDate.indexOf(".") > -1) ? "dd.mm.yyyy" : ((minDate.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
minDateFormat.replace(/(yyyy|dd|mm)/g, function(part) { minDateFmt[part] = j++; });
var minDateParts = minDate.match(/(\d+)/g);
var valueParts = value.match(/(\d+)/g);
minDate = new Date(minDateParts[minDateFmt["yyyy"]], minDateParts[minDateFmt["mm"]]-1, minDateParts[minDateFmt["dd"]],0,0,0,0);
if (options.shift) {
var shift = options.shift;
day = minDate.getDate();
day = day + parseInt(shift);
minDate.setDate(day);
}
value = new Date(valueParts[fmt["yyyy"]], valueParts[fmt["mm"]]-1, valueParts[fmt["dd"]],0,0,0,0);
check = value <= minDate;
}
return this.optional(element) || check;
}, function(options, element) {
// validation message
if (options.fromField) {
var minDate = "";
var fieldId = options.value;
var field = document.getElementById(fieldId);
if (field) {
minDate = field.value;
}
} else {
minDate = options.value;
}
var format, minDateFormat, j = 0, minDateFmt = {}, day, month, year, valDate;
minDateFormat = (minDate.indexOf(".") > -1) ? "dd.mm.yyyy" : ((minDate.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
minDateFormat.replace(/(yyyy|dd|mm)/g, function(part) { minDateFmt[part] = j++; });
var minDateParts = minDate.match(/(\d+)/g);
minDate = new Date(minDateParts[minDateFmt["yyyy"]], minDateParts[minDateFmt["mm"]]-1, minDateParts[minDateFmt["dd"]],0,0,0,0);
if (options.shift) {
var shift = options.shift;
day = minDate.getDate();
day = day + parseInt(shift);
minDate.setDate(day);
}
format = options.format;
valDate = "";
day = minDate.getDate();
if (day < 10) {
day = "0" + day;
}
month = 1 + minDate.getMonth();
if (month < 10) {
month = "0" + month;
}
year = minDate.getFullYear();
switch (format) {
case "%Y-%m-%d" :
valDate = year + "-" + month + "-" + day;
break;
case "%m/%d/%Y" :
valDate = month + "/" + day + "/" + year;
break;
default :
valDate = day + "." + month + "." + year;
break;
}
return jQuery.validator.format("' . addslashes(Text::_('COM_VISFORMS_MAXDATE_VALIDATION_FAILED_JS')) . '", valDate);
});
jQuery.validator.addMethod("minage", function (value, element, options) {
let check = false, minage = "", age = "", format, i = 0, fmt = {}, valueParts, years, now = new Date();
// a date is selected
if (value) {
// no minage set
if (options.minage) {
minage = options.minage;
}
else {
return true;
}
// get year, month and day from selected date
// with regards to the currently used format
format = (value.indexOf(".") > -1) ? "dd.mm.yyyy" : ((value.indexOf("/") > -1) ? "mm/dd/yyyy" : "yyyy-mm-dd");
format.replace(/(yyyy|dd|mm)/g, function(part) { fmt[part] = i++; });
valueParts = value.match(/(\d+)/g);
value = new Date(valueParts[fmt["yyyy"]], valueParts[fmt["mm"]]-1, valueParts[fmt["dd"]],0,0,0,0);
// get the difference between the year of now and the selected date
years = now.getFullYear() - value.getFullYear();
// set year in selected date to current year
value.setFullYear(value.getFullYear() + years);
// if the selected date is then in the future, substact 1 from years, because the last year is not yet completed
if (value > now) {
years--;
}
check = years >= minage;
}
return this.optional(element) || check;
});
jQuery.validator.addMethod("phonevalidation", function (value, element, options) {
let check = false, format, regex;
// a phonenumber is given
if (value) {
// get validation type
if (options.phonevalidation) {
format = options.phonevalidation;
}
else {
return true;
}
switch (format) {
case "NANP" :
regex = /^(?:\+?1[-. ]?)?\(?([2-9][0-8][0-9])\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/;
break;
case "ITU-T" :
regex = /^\+(?:[0-9] ?){6,14}[0-9]$/;
break;
case "EPP" :
regex = /^\+[0-9]{1,3}\.[0-9]{4,14}(?:x.+)?$/;
break;
default :
return true;
}
check = (value === "" || regex.test(value));
}
return this.optional(element) || check;
});
});';
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->addInlineScript($script, [], ['type' => 'module'], []);
static::$loaded[__METHOD__] = true;
}
public static function fixLinksInMail($text) {
$urlPattern = '/^(http|https|ftp|mailto|tel)\:.*$/i';
$aPattern = '/<[ ]*a[^>]+href=[("\')]([^("\')]*)/';
$imgPattern = '/<[ ]*img[^>]+src=[("\')]([^("\')]*)/';
if (preg_match_all($aPattern, $text, $hrefs)) {
$unique_urls = array_unique($hrefs[1]);
foreach ($unique_urls as $href) {
if (empty($href)) {
continue;
}
if (!(preg_match($urlPattern, $href) == 1)) {
//we deal with an intern Url without Root path
$link = Uri::base() . $href;
$newText = preg_replace('\'' . preg_quote($href) . '\'', $link, $text);
$text = $newText;
}
}
}
if (preg_match_all($imgPattern, $text, $srcs)) {
$unique_image = array_unique($srcs[1]);
foreach ($unique_image as $src) {
if (file_exists($src)) {
//we deal with a local img
if (!(preg_match('\'' . preg_quote(Uri::base()) . '\'', $src) == 1)) {
//we deal with an intern Url without base Uri
$link = Uri::base() . $src;
$newText = preg_replace('\'' . preg_quote($src) . '\'', $link, $text);
$text = $newText;
}
}
}
}
return $text;
}
// ToDo parameter $tip, jsFunction no longer needed
// this is a copy of HTMLHelper::_(gird.sort...
// necessary to use our own function because we cannot change the icon prefix in Joomla! grid.sort function into visicon
// and to allow multiple sort forms on one page (since Visforms 3.7.1)
public static function sort($title, $order, $direction = 'asc', $selected = '', $task = null, $new_direction = 'asc', $tip = '', $context = 'adminForm', $jsFunction = "Joomla.tableOrdering", $unSortable = false) {
$title = Text::_($title);
if (!empty($unSortable)) {
return Text::_($title);
}
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa->useScript('core');
$wa->registerAndUseScript('com_visforms.visformsdata', 'media/com_visforms/js/visforms-dataview.js', [], ['defer' => true]);
$helpText = htmlspecialchars(Text::_('JGLOBAL_CLICK_TO_SORT_THIS_COLUMN') . ': ' . $title, ENT_COMPAT);
HTMLHelper::_('bootstrap.tooltip');
$direction = strtolower($direction);
$icon = array('arrow-up-3', 'arrow-down-3');
$index = (int) ($direction == 'desc');
if ($order != $selected) {
$direction = $new_direction;
}
else {
$direction = ($direction == 'desc') ? 'asc' : 'desc';
}
$html = array();
$html[] = '