first commit
This commit is contained in:
commit
b4e8cbe182
10213 files changed
+3125839
No files matched your search
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'dependencies' => array(),
|
||||
'version' => WPCF7_VERSION,
|
||||
);
|
||||
@@ -0,0 +1 @@
|
||||
(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};function i(t){if(this.formData={},this.tree={},!(t instanceof FormData))return this;this.formData=t;const e=()=>{const t=new Map;return t.largestIndex=0,t.set=function(e,i){""===e?e=t.largestIndex++:/^[0-9]+$/.test(e)&&(e=parseInt(e),t.largestIndex<=e&&(t.largestIndex=e+1)),Map.prototype.set.call(t,e,i)},t};this.tree=e();const i=/^(?<name>[a-z][-a-z0-9_:]*)(?<array>(?:\[(?:[a-z][-a-z0-9_:]*|[0-9]*)\])*)/i;for(const[t,s]of this.formData){const o=t.match(i);if(o)if(""===o.groups.array)this.tree.set(o.groups.name,s);else{const t=[...o.groups.array.matchAll(/\[([a-z][-a-z0-9_:]*|[0-9]*)\]/gi)].map((([t,e])=>e));t.unshift(o.groups.name);const i=t.pop();t.reduce(((t,i)=>{if(/^[0-9]+$/.test(i)&&(i=parseInt(i)),t.get(i)instanceof Map)return t.get(i);const s=e();return t.set(i,s),s}),this.tree).set(i,s)}}}t.r(e),t.d(e,{all:()=>D,any:()=>M,date:()=>f,dayofweek:()=>u,email:()=>r,enum:()=>h,file:()=>m,maxdate:()=>z,maxfilesize:()=>$,maxitems:()=>v,maxlength:()=>x,maxnumber:()=>b,mindate:()=>A,minfilesize:()=>j,minitems:()=>w,minlength:()=>g,minnumber:()=>y,number:()=>c,required:()=>n,requiredfile:()=>a,tel:()=>l,time:()=>d,url:()=>p}),i.prototype.entries=function(){return this.tree.entries()},i.prototype.get=function(t){return this.tree.get(t)},i.prototype.getAll=function(t){if(!this.has(t))return[];const e=t=>{const i=[];if(t instanceof Map)for(const[s,o]of t)i.push(...e(o));else""!==t&&i.push(t);return i};return e(this.get(t))},i.prototype.has=function(t){return this.tree.has(t)},i.prototype.keys=function(){return this.tree.keys()},i.prototype.values=function(){return this.tree.values()};const s=i;function o({rule:t,field:e,error:i,...s}){this.rule=t,this.field=e,this.error=i,this.properties=s}const n=function(t){if(0===t.getAll(this.field).length)throw new o(this)},a=function(t){if(0===t.getAll(this.field).length)throw new o(this)},r=function(t){if(!t.getAll(this.field).every((t=>{if((t=t.trim()).length<6)return!1;if(-1===t.indexOf("@",1))return!1;if(t.indexOf("@")!==t.lastIndexOf("@"))return!1;const[e,i]=t.split("@",2);if(!/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/.test(e))return!1;if(/\.{2,}/.test(i))return!1;if(/(?:^[ \t\n\r\0\x0B.]|[ \t\n\r\0\x0B.]$)/.test(i))return!1;const s=i.split(".");if(s.length<2)return!1;for(const t of s){if(/(?:^[ \t\n\r\0\x0B-]|[ \t\n\r\0\x0B-]$)/.test(t))return!1;if(!/^[a-z0-9-]+$/i.test(t))return!1}return!0})))throw new o(this)},p=function(t){const e=t.getAll(this.field);if(!e.every((t=>{if(""===(t=t.trim()))return!1;try{return(t=>-1!==["http","https","ftp","ftps","mailto","news","irc","irc6","ircs","gopher","nntp","feed","telnet","mms","rtsp","sms","svn","tel","fax","xmpp","webcal","urn"].indexOf(t))(new URL(t).protocol.replace(/:$/,""))}catch{return!1}})))throw new o(this)},l=function(t){if(!t.getAll(this.field).every((t=>(t=(t=t.trim()).replaceAll(/[()/.*#\s-]+/g,""),/^[+]?[0-9]+$/.test(t)))))throw new o(this)},c=function(t){if(!t.getAll(this.field).every((t=>(t=t.trim(),!!/^[-]?[0-9]+(?:[eE][+-]?[0-9]+)?$/.test(t)||!!/^[-]?(?:[0-9]+)?[.][0-9]+(?:[eE][+-]?[0-9]+)?$/.test(t)))))throw new o(this)},f=function(t){if(!t.getAll(this.field).every((t=>{if(t=t.trim(),!/^[0-9]{4,}-[0-9]{2}-[0-9]{2}$/.test(t))return!1;const e=new Date(t);return!Number.isNaN(e.valueOf())})))throw new o(this)},d=function(t){if(!t.getAll(this.field).every((t=>{const e=t.trim().match(/^([0-9]{2})\:([0-9]{2})(?:\:([0-9]{2}))?$/);if(!e)return!1;const i=parseInt(e[1]),s=parseInt(e[2]),o=e[3]?parseInt(e[3]):0;return 0<=i&&i<=23&&0<=s&&s<=59&&0<=o&&o<=59})))throw new o(this)},m=function(t){if(!t.getAll(this.field).every((t=>t instanceof File&&this.accept?.some((e=>/^\.[a-z0-9]+$/i.test(e)?t.name.toLowerCase().endsWith(e.toLowerCase()):(t=>{const e=[],i=t.match(/^(?<toplevel>[a-z]+)\/(?<sub>[*]|[a-z0-9.+-]+)$/i);if(i){const t=i.groups.toplevel.toLowerCase(),s=i.groups.sub.toLowerCase();for(const[o,n]of(()=>{const t=new Map;return t.set("jpg|jpeg|jpe","image/jpeg"),t.set("gif","image/gif"),t.set("png","image/png"),t.set("bmp","image/bmp"),t.set("tiff|tif","image/tiff"),t.set("webp","image/webp"),t.set("ico","image/x-icon"),t.set("heic","image/heic"),t.set("asf|asx","video/x-ms-asf"),t.set("wmv","video/x-ms-wmv"),t.set("wmx","video/x-ms-wmx"),t.set("wm","video/x-ms-wm"),t.set("avi","video/avi"),t.set("divx","video/divx"),t.set("flv","video/x-flv"),t.set("mov|qt","video/quicktime"),t.set("mpeg|mpg|mpe","video/mpeg"),t.set("mp4|m4v","video/mp4"),t.set("ogv","video/ogg"),t.set("webm","video/webm"),t.set("mkv","video/x-matroska"),t.set("3gp|3gpp","video/3gpp"),t.set("3g2|3gp2","video/3gpp2"),t.set("txt|asc|c|cc|h|srt","text/plain"),t.set("csv","text/csv"),t.set("tsv","text/tab-separatedLine truncated
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* The base class of SWV rules.
|
||||
*/
|
||||
abstract class Rule {
|
||||
|
||||
protected $properties = array();
|
||||
|
||||
public function __construct( $properties = '' ) {
|
||||
$this->properties = wp_parse_args( $properties, array() );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this rule matches the given context.
|
||||
*
|
||||
* @param array $context Context.
|
||||
*/
|
||||
public function matches( $context ) {
|
||||
$field = $this->get_property( 'field' );
|
||||
|
||||
if ( ! empty( $context['field'] ) ) {
|
||||
if ( $field and ! in_array( $field, (array) $context['field'], true ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates with this rule's logic.
|
||||
*
|
||||
* @param array $context Context.
|
||||
*/
|
||||
public function validate( $context ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts the properties to an array.
|
||||
*
|
||||
* @return array Array of properties.
|
||||
*/
|
||||
public function to_array() {
|
||||
$properties = (array) $this->properties;
|
||||
|
||||
if ( defined( 'static::rule_name' ) and static::rule_name ) {
|
||||
$properties = array( 'rule' => static::rule_name ) + $properties;
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the property value specified by the given property name.
|
||||
*
|
||||
* @param string $name Property name.
|
||||
* @return mixed Property value.
|
||||
*/
|
||||
public function get_property( $name ) {
|
||||
if ( isset( $this->properties[$name] ) ) {
|
||||
return $this->properties[$name];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the default user input value from $_POST.
|
||||
*
|
||||
* @return mixed Default user input value.
|
||||
*/
|
||||
public function get_default_input() {
|
||||
$field = $this->get_property( 'field' );
|
||||
|
||||
if ( isset( $_POST[$field] ) ) {
|
||||
return wp_unslash( $_POST[$field] );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an error object. Returns false if the error property is omitted.
|
||||
*/
|
||||
protected function create_error() {
|
||||
$error_code = defined( 'static::rule_name' )
|
||||
? sprintf( 'swv_%s', static::rule_name )
|
||||
: 'swv';
|
||||
|
||||
return new WP_Error(
|
||||
$error_code,
|
||||
(string) $this->get_property( 'error' ),
|
||||
$this
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The base class of SWV composite rules.
|
||||
*/
|
||||
abstract class CompositeRule extends Rule {
|
||||
|
||||
protected $rules = array();
|
||||
|
||||
|
||||
/**
|
||||
* Adds a sub-rule to this composite rule.
|
||||
*
|
||||
* @param Rule $rule Sub-rule to be added.
|
||||
*/
|
||||
public function add_rule( $rule ) {
|
||||
if ( $rule instanceof Rule ) {
|
||||
$this->rules[] = $rule;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator of sub-rules.
|
||||
*/
|
||||
public function rules() {
|
||||
foreach ( $this->rules as $rule ) {
|
||||
yield $rule;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if this rule matches the given context.
|
||||
*
|
||||
* @param array $context Context.
|
||||
*/
|
||||
public function matches( $context ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates with this rule's logic.
|
||||
*
|
||||
* @param array $context Context.
|
||||
*/
|
||||
public function validate( $context ) {
|
||||
foreach ( $this->rules() as $rule ) {
|
||||
if ( $rule->matches( $context ) ) {
|
||||
$result = $rule->validate( $context );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts the properties to an array.
|
||||
*
|
||||
* @return array Array of properties.
|
||||
*/
|
||||
public function to_array() {
|
||||
$rules_arrays = array_map(
|
||||
static function ( $rule ) {
|
||||
return $rule->to_array();
|
||||
},
|
||||
$this->rules
|
||||
);
|
||||
|
||||
return array_merge(
|
||||
parent::to_array(),
|
||||
array(
|
||||
'rules' => $rules_arrays,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class AllRule extends CompositeRule {
|
||||
|
||||
const rule_name = 'all';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
foreach ( $this->rules() as $rule ) {
|
||||
if ( $rule->matches( $context ) ) {
|
||||
$result = $rule->validate( $context );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
if ( $result->get_error_message() ) {
|
||||
return $result;
|
||||
} else {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class AnyRule extends CompositeRule {
|
||||
|
||||
const rule_name = 'any';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
foreach ( $this->rules() as $rule ) {
|
||||
if ( $rule->matches( $context ) ) {
|
||||
$result = $rule->validate( $context );
|
||||
|
||||
if ( ! is_wp_error( $result ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class DateRule extends Rule {
|
||||
|
||||
const rule_name = 'date';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! wpcf7_is_date( $i ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class DayofweekRule extends Rule {
|
||||
|
||||
const rule_name = 'dayofweek';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$acceptable_values = (array) $this->get_property( 'accept' );
|
||||
$acceptable_values = array_map( 'intval', $acceptable_values );
|
||||
$acceptable_values = array_filter( $acceptable_values );
|
||||
$acceptable_values = array_unique( $acceptable_values );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( wpcf7_is_date( $i ) ) {
|
||||
$datetime = date_create_immutable( $i, wp_timezone() );
|
||||
$dow = (int) $datetime->format( 'N' );
|
||||
|
||||
if ( ! in_array( $dow, $acceptable_values, true ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class EmailRule extends Rule {
|
||||
|
||||
const rule_name = 'email';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! wpcf7_is_email( $i ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class EnumRule extends Rule {
|
||||
|
||||
const rule_name = 'enum';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$acceptable_values = (array) $this->get_property( 'accept' );
|
||||
$acceptable_values = array_map( 'strval', $acceptable_values );
|
||||
$acceptable_values = array_unique( $acceptable_values );
|
||||
|
||||
$acceptable_values = array_filter( $acceptable_values,
|
||||
static function ( $val ) {
|
||||
return '' !== $val;
|
||||
}
|
||||
);
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! in_array( $i, $acceptable_values, true ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class FileRule extends Rule {
|
||||
|
||||
const rule_name = 'file';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['file'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$field = $this->get_property( 'field' );
|
||||
$input = $_FILES[$field]['name'] ?? '';
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$acceptable_filetypes = array();
|
||||
|
||||
foreach ( (array) $this->get_property( 'accept' ) as $accept ) {
|
||||
if ( preg_match( '/^\.[a-z0-9]+$/i', $accept ) ) {
|
||||
$acceptable_filetypes[] = strtolower( $accept );
|
||||
} else {
|
||||
foreach ( wpcf7_convert_mime_to_ext( $accept ) as $ext ) {
|
||||
$acceptable_filetypes[] = sprintf(
|
||||
'.%s',
|
||||
strtolower( trim( $ext, ' .' ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$acceptable_filetypes = array_unique( $acceptable_filetypes );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
$last_period_pos = strrpos( $i, '.' );
|
||||
|
||||
if ( false === $last_period_pos ) { // no period
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
$suffix = strtolower( substr( $i, $last_period_pos ) );
|
||||
|
||||
if ( ! in_array( $suffix, $acceptable_filetypes, true ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MaxDateRule extends Rule {
|
||||
|
||||
const rule_name = 'maxdate';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( ! wpcf7_is_date( $threshold ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( wpcf7_is_date( $i ) and $threshold < $i ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MaxFileSizeRule extends Rule {
|
||||
|
||||
const rule_name = 'maxfilesize';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['file'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$field = $this->get_property( 'field' );
|
||||
$input = $_FILES[$field]['size'] ?? '';
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
if ( empty( $input ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( $threshold < array_sum( $input ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MaxItemsRule extends Rule {
|
||||
|
||||
const rule_name = 'maxitems';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( ! wpcf7_is_number( $threshold ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( (int) $threshold < count( $input ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MaxLengthRule extends Rule {
|
||||
|
||||
const rule_name = 'maxlength';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
if ( empty( $input ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$total = 0;
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
$total += wpcf7_count_code_units( $i );
|
||||
}
|
||||
|
||||
$threshold = (int) $this->get_property( 'threshold' );
|
||||
|
||||
if ( $total <= $threshold ) {
|
||||
return true;
|
||||
} else {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MaxNumberRule extends Rule {
|
||||
|
||||
const rule_name = 'maxnumber';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( ! wpcf7_is_number( $threshold ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( wpcf7_is_number( $i ) and (float) $threshold < (float) $i ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MinDateRule extends Rule {
|
||||
|
||||
const rule_name = 'mindate';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( ! wpcf7_is_date( $threshold ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( wpcf7_is_date( $i ) and $i < $threshold ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MinFileSizeRule extends Rule {
|
||||
|
||||
const rule_name = 'minfilesize';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['file'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$field = $this->get_property( 'field' );
|
||||
$input = $_FILES[$field]['size'] ?? '';
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
if ( empty( $input ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( array_sum( $input ) < $threshold ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MinItemsRule extends Rule {
|
||||
|
||||
const rule_name = 'minitems';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( ! wpcf7_is_number( $threshold ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( count( $input ) < (int) $threshold ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MinLengthRule extends Rule {
|
||||
|
||||
const rule_name = 'minlength';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
if ( empty( $input ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$total = 0;
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
$total += wpcf7_count_code_units( $i );
|
||||
}
|
||||
|
||||
$threshold = (int) $this->get_property( 'threshold' );
|
||||
|
||||
if ( $threshold <= $total ) {
|
||||
return true;
|
||||
} else {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class MinNumberRule extends Rule {
|
||||
|
||||
const rule_name = 'minnumber';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
$threshold = $this->get_property( 'threshold' );
|
||||
|
||||
if ( ! wpcf7_is_number( $threshold ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( wpcf7_is_number( $i ) and (float) $i < (float) $threshold ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class NumberRule extends Rule {
|
||||
|
||||
const rule_name = 'number';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! wpcf7_is_number( $i ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class RequiredRule extends Rule {
|
||||
|
||||
const rule_name = 'required';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
if ( empty( $input ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class RequiredFileRule extends Rule {
|
||||
|
||||
const rule_name = 'requiredfile';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['file'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$field = $this->get_property( 'field' );
|
||||
$input = $_FILES[$field]['tmp_name'] ?? '';
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
if ( empty( $input ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class TelRule extends Rule {
|
||||
|
||||
const rule_name = 'tel';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! wpcf7_is_tel( $i ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class TimeRule extends Rule {
|
||||
|
||||
const rule_name = 'time';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! wpcf7_is_time( $i ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Contactable\SWV;
|
||||
|
||||
class URLRule extends Rule {
|
||||
|
||||
const rule_name = 'url';
|
||||
|
||||
public function matches( $context ) {
|
||||
if ( false === parent::matches( $context ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $context['text'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function validate( $context ) {
|
||||
$input = $this->get_default_input();
|
||||
$input = wpcf7_array_flatten( $input );
|
||||
$input = wpcf7_exclude_blank( $input );
|
||||
|
||||
foreach ( $input as $i ) {
|
||||
if ( ! wpcf7_is_url( $i ) ) {
|
||||
return $this->create_error();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
trait WPCF7_SWV_SchemaHolder {
|
||||
|
||||
protected $schema;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves SWV schema for this holder object (contact form).
|
||||
*
|
||||
* @return WPCF7_SWV_Schema The schema object.
|
||||
*/
|
||||
public function get_schema() {
|
||||
if ( isset( $this->schema ) ) {
|
||||
return $this->schema;
|
||||
}
|
||||
|
||||
$schema = new WPCF7_SWV_Schema( array(
|
||||
'locale' => isset( $this->locale ) ? $this->locale : '',
|
||||
) );
|
||||
|
||||
do_action( 'wpcf7_swv_create_schema', $schema, $this );
|
||||
|
||||
return $this->schema = $schema;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates form inputs based on the schema and given context.
|
||||
*/
|
||||
public function validate_schema( $context, WPCF7_Validation $validity ) {
|
||||
$schema = $this->get_schema();
|
||||
|
||||
foreach ( $schema->validate( $context ) as $result ) {
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$rule = $result->get_error_data();
|
||||
$field = $rule->get_property( 'field' );
|
||||
|
||||
if ( isset( $field ) and $validity->is_valid( $field ) ) {
|
||||
$validity->invalidate( $field, $result );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
static function () {
|
||||
$assets = array();
|
||||
$asset_file = wpcf7_plugin_path( 'includes/swv/js/index.asset.php' );
|
||||
|
||||
if ( file_exists( $asset_file ) ) {
|
||||
$assets = include( $asset_file );
|
||||
}
|
||||
|
||||
$assets = wp_parse_args( $assets, array(
|
||||
'dependencies' => array(),
|
||||
'version' => WPCF7_VERSION,
|
||||
) );
|
||||
|
||||
wp_register_script( 'swv',
|
||||
wpcf7_plugin_url( 'includes/swv/js/index.js' ),
|
||||
$assets['dependencies'],
|
||||
$assets['version'],
|
||||
array( 'in_footer' => true )
|
||||
);
|
||||
},
|
||||
10, 0
|
||||
);
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
/**
|
||||
* Schema-Woven Validation API
|
||||
*/
|
||||
|
||||
require_once WPCF7_PLUGIN_DIR . '/includes/swv/schema-holder.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/includes/swv/script-loader.php';
|
||||
require_once WPCF7_PLUGIN_DIR . '/includes/swv/php/abstract-rules.php';
|
||||
|
||||
|
||||
/**
|
||||
* Returns an associative array of SWV rules.
|
||||
*/
|
||||
function wpcf7_swv_available_rules() {
|
||||
$rules = array(
|
||||
'required' => 'Contactable\SWV\RequiredRule',
|
||||
'requiredfile' => 'Contactable\SWV\RequiredFileRule',
|
||||
'email' => 'Contactable\SWV\EmailRule',
|
||||
'url' => 'Contactable\SWV\URLRule',
|
||||
'tel' => 'Contactable\SWV\TelRule',
|
||||
'number' => 'Contactable\SWV\NumberRule',
|
||||
'date' => 'Contactable\SWV\DateRule',
|
||||
'time' => 'Contactable\SWV\TimeRule',
|
||||
'file' => 'Contactable\SWV\FileRule',
|
||||
'enum' => 'Contactable\SWV\EnumRule',
|
||||
'dayofweek' => 'Contactable\SWV\DayofweekRule',
|
||||
'minitems' => 'Contactable\SWV\MinItemsRule',
|
||||
'maxitems' => 'Contactable\SWV\MaxItemsRule',
|
||||
'minlength' => 'Contactable\SWV\MinLengthRule',
|
||||
'maxlength' => 'Contactable\SWV\MaxLengthRule',
|
||||
'minnumber' => 'Contactable\SWV\MinNumberRule',
|
||||
'maxnumber' => 'Contactable\SWV\MaxNumberRule',
|
||||
'mindate' => 'Contactable\SWV\MinDateRule',
|
||||
'maxdate' => 'Contactable\SWV\MaxDateRule',
|
||||
'minfilesize' => 'Contactable\SWV\MinFileSizeRule',
|
||||
'maxfilesize' => 'Contactable\SWV\MaxFileSizeRule',
|
||||
'all' => 'Contactable\SWV\AllRule',
|
||||
'any' => 'Contactable\SWV\AnyRule',
|
||||
);
|
||||
|
||||
return apply_filters( 'wpcf7_swv_available_rules', $rules );
|
||||
}
|
||||
|
||||
|
||||
add_action( 'wpcf7_init', 'wpcf7_swv_load_rules', 10, 0 );
|
||||
|
||||
/**
|
||||
* Loads SWV fules.
|
||||
*/
|
||||
function wpcf7_swv_load_rules() {
|
||||
$rules = wpcf7_swv_available_rules();
|
||||
|
||||
foreach ( array_keys( $rules ) as $rule ) {
|
||||
$file = sprintf( '%s.php', $rule );
|
||||
$path = path_join( WPCF7_PLUGIN_DIR . '/includes/swv/php/rules', $file );
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
include_once $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an SWV rule object.
|
||||
*
|
||||
* @param string $rule_name Rule name.
|
||||
* @param string|array $properties Optional. Rule properties.
|
||||
* @return \Contactable\SWV\Rule|null The rule object, or null if it failed.
|
||||
*/
|
||||
function wpcf7_swv_create_rule( $rule_name, $properties = '' ) {
|
||||
$rules = wpcf7_swv_available_rules();
|
||||
|
||||
if ( isset( $rules[$rule_name] ) ) {
|
||||
return new $rules[$rule_name]( $properties );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an associative array of JSON Schema for Contact Form 7 SWV.
|
||||
*/
|
||||
function wpcf7_swv_get_meta_schema() {
|
||||
return array(
|
||||
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
|
||||
'title' => 'Contact Form 7 SWV',
|
||||
'description' => 'Contact Form 7 SWV meta-schema',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'version' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'locale' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'rules' => array(
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'rule' => array(
|
||||
'type' => 'string',
|
||||
'enum' => array_keys( wpcf7_swv_available_rules() ),
|
||||
),
|
||||
'field' => array(
|
||||
'type' => 'string',
|
||||
'pattern' => '^[A-Za-z][-A-Za-z0-9_:]*$',
|
||||
),
|
||||
'error' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'accept' => array(
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'threshold' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'required' => array( 'rule' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The schema class as a composite rule.
|
||||
*/
|
||||
class WPCF7_SWV_Schema extends \Contactable\SWV\CompositeRule {
|
||||
|
||||
/**
|
||||
* The human-readable version of the schema.
|
||||
*/
|
||||
const version = 'Contact Form 7 SWV Schema 2024-02';
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct( $properties = '' ) {
|
||||
$this->properties = wp_parse_args( $properties, array(
|
||||
'version' => self::version,
|
||||
) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates with this schema.
|
||||
*
|
||||
* @param array $context Context.
|
||||
*/
|
||||
public function validate( $context ) {
|
||||
foreach ( $this->rules() as $rule ) {
|
||||
if ( $rule->matches( $context ) ) {
|
||||
yield $rule->validate( $context );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user