M\á:l‹°;ZfbJôØèÞ®^—X£ß (qª·vÓIÍnÛ³séRÈEÜ]ð>=½ô €“²ñ–ïsHƒR<¿×™¦.¤yÈrHl‚·üêãpÞ´-)QAù€pëægÇv¼T†¶�hnç+4(ê8¸>€²¼ý»T%díã<35zn7;%¡á,9ª[CéP¶ýÓȤÁNnÔþ¯s€ªñ.²”¥¢ø �GYŠé<�9q+�#‰~™Þá!våÚ²(¥E讑ûÄÙIP×yô½Â<}mƒMôicKo­³½ò!Ö‘õç¶�¡‡ÔŠUÚ‰¡ƒ@¨¥NìƒP­=IuGdk˜ø8Në�L]û-e™k:a…ü�g§ü²�Ìxaò—±‹‡-_Fc´�¿Ûý áö_•+ËP�yyŒtC$¤Õé¬ÔÑ~ö)œVIly ç`F…*üG0è#L "¡èH?JXöÒ¡‹�þ öDT’È‘ûX2]ÐS×Ôò£_W9,ª¦ÞKìßÌÒ b¡ÀŽŠˆë³Ï â½iY�îî �TAt©ª1Óc¬ÌÔ¢¸Ü¶JNo‘²Sljg1vKv¤ø›à¤ÐŠ¥7=È9ÞtýõhPÏEv�¾ÞyÀx'' ¨ë�ئÕé±µVª°›3@œ .†éN£©räÂÒi/QH\0âÀ©Rs ùà²,Õªf)kÌô´ÌɱBÔ7ay!‚ñ¬6ÐÌžÓ7%"¢-³JmõÓêîçè4upp6Á«óqs œdh—Ý¥§Tx%ÏšKM;VœÞÉV·�)9[ =ãÈ#5¸Bk¹8”%ŸZ¨ãÀ e‡.Ã6õí~ñý8L¹Ô€z»¯^½±.øûvàï¹Û:ޏâôlÐy/Fž¼È‡RŒ+sëæÃ{ªr¼TNumŒ~£�™^Å,:¡Äl5ú|:ÿ5¼}²Â†}O_ Ÿ”]&LØ{ìš0V˜Šujµsaêt_•Ï›YNªQ™!CtwÞ»$þŽ‚T9S=ÒBïâëVë +;ĈŽ#Fà‹í¯J¸Mä1Xì˜!üæêÆb_íHÊñw;y±�·ÔÅÞq™±ZÛ¸-´‹{¡Ä~‚”ôv1:ç÷þß= G3�´IP[n Gìmûš ~e-¼;p†ý²¿3üài%‰À|“Ry›��&楼ÈÄ©øß]é!ÌÍε< W´Uþö�¥L¥Ž+íD¾°†’©©¬Izøý­_©‰Šè×8xS@ÌÿÚm¦môse˜÷Ùâ”Èz¤æŽ${€Œtãkf†“HA°ÃòEdw�*ØÕ·¬Œ¿O&Àƒ¿BµY2¸o¼ç.œ¯&x›•µØ…ÀØŠøà‹í¯J¸Mä1Xì˜!üæêÆb_íHÊñw;y±�Nˆž~-]Ź—Œ ¡”MعBBVÌ„.i~àûCŽUܼød(4¯ÚUÒaìÇÆž/5!kR¾“«ŠLæŽ${€Œtãkf†“HA°ÃòEdw�*ØÕ·¬Œ¥Ÿë®OÑʈy®BÛ_¿?–„‰ûþ‹lk̪Só±™Õà¸B€¼qõ§€—ˆhHóNf¬i �ö¯J^pËoH}OlCÂ&cá|aRó8ˆ�›�ÙÃ’KU2Y_ÙÄGÔDjù”õÄ“s$_¾{ªIèÐôÉmkáŸi:>ïÒcµÌÖI ï+¿Eò Ÿ”]&LØ{ìš0V˜Šu¹Ô€z»¯^½±.øûvàïñ…Sµµeœƒ¿q }ÇßïÒcµÌÖI ï+¿Eò Ÿ”]&LØ{ìš0V˜Šu¹Ô€z»¯^½±.øûvà¿-Zæ‹c&¯Ø6Ïéìºha’jI²µÁ"§¸óÉÀbÿˆi“/‚¶9Rÿ°pÁÙsMè…)ëÚ0è 4Ëà‹í¯J¸Mä1Xì˜!üæêÆb_íHÊñw;y±�Nˆž~-]Ź—Œ ¡”M (ÜG· éä\“Üû®t/A«Í!SN$_¶_Ìœ‘±–ŒW¥Ô™¶xýE·‘™¾·H(&ìïhµŠ €\ù–¾!n·}µª¿÷ëϽYÅz¥æl˜~C饉jJÊç«–©7@}ûv5•¥Kǃha’jI²µÁ"§¸óÉ/¨û"Ôï®üžqXôh�Ψ܆/M¼/„š9óÿÙØGNf¬i �ö¯J^pËoH}OlCÂ&cá|aGm×ëFHÓ”è@rKȳ@Ša�ƒH^>^ï<­g>ïÒcµÌÖI ï+¿Eò Ÿ”]&LØ{ìš0V˜Šu¹“Ý<–ŒÁ¦Xé¶RÇõÆm5à£0ñú×í(r:’i“`ž�ö˜¿›ü}ŒÜX9˜¦´J¹PuƒG»qí�à%‰À|“Ry›��&楼ÈÄ©øß]é!ÌÍε< W´Uè@:|[ù5³É ɹ°Nþ;LÕ›—7“â4]ïº 2ŠA”Ûô6B:¯S•'×Êã�Å¢:ZT‘mâ�ó•~è:TÄfpwiEQoõ6΋AžªÍ’j•õ®î‘ë!Tžõ^º§Þ#‘mÆ,fœ·˜ys“×ÿtw6Ta„Êýë$÷Â}ææmU·ærr7Aï\ÿI᳘T¸o(€½Ë¦}QA€ó ±í…Õí9pºkÓ¤äŠòÊ¥»¼AŸÊÅÜ™vìvð4ÂØ(â�ä.-…»ð¹$ã)ðˆ{;9Ê-ÚîÊ‹þK—Ƕ۴Vž.µïÆzWc=Ù.æ] [2I'®½|¢©¨§×…+ž>>DÆqJ�d)Ч‰öÀ_רà&ŒgÓ½ËSí±$Ha"û­ÆAÛZ篸LËŽöà`N‡ìK¹-æg(Ê~ #Øœ`°ŸF³�íª64 Æt G㎌3>ݳ×ÀòÇǃ•Âô…ä!2.cö€bÚ-Yر”µ'ê6 âæÌ OÞ}0^ß8XTÔ$ÉKj÷Ñæ¾.òØÁ.°íƒƒ˜Þ)kºòµSOjËþsœÉl®s0×Næ…ò—òüîÅi¶¢öv¸~‡@ywµç°+eÅÎÖmrV‚}àYë vÇ·FoÎVý¼œÜyÄÀÅV-†¹õ'†ö«½jºe_…„iˆß¿-{W½ÀÞÏ’ÇÚõÒìÔþýì]Èd�7›{®¯™ÜŸç¿Ò_¸nÁ’>Œ¹Ö+YMq-gc÷¿žù™+]”ô“NdéÁõš»VC89þ\Í9)íÞF¡"Ù‰¨YBÁP¬÷äLøÄ“H×¶o‡­ˆtSÙ“qB³ W@Èm½�Éàø¢È¥:¡os·4Á1&ËPñFw—GàJâKF³°Óþ `7»àĪÓÿ�ã]ÅØùy"ÖüßáG¸Có |†.~¥´&ÐÕ> Ù4|ß)Üô|A•5FÁÿ¡º»5t ÇÈnàM7E;ñ²¾}_Àš5¼,û€ ®ß�ŒO[¨ó©¨8¯ ó®>ÌÙÎŽùtcÝ\³À1ƒwXl¬Å3û,d|‡Š¡ÐMËÕ¸ùêÁ¾Ž°HMf½Á|ê*šôð’ ÄÊE2€hª�GþÆï¨k°éÅ33t1|âÆ�€ÅìŽÝ:°fŸÓoIÈÁû?nŽ[=÷'ZœÂÐ |™•õã×ÎE.¼9W­¸n%)9!0e[9x>?jd}·‰»}÷ñ´žîˆ4F9¤„S¢[—¸oWÞè§Ö¿{ì÷‡BÕ™ v2ö3å®EÅ®5tSä1„c�ˆý/) ²‡j³d'Ý0r¹båj¢ ;{"ÌûZ&.�·å'§êÀüj »õ>LÞ”alÖn 2=’Iâ.s‰OÒéŸ ù0-ݾQç1XØɇÎÁž}™Â¦üÓ­�~Rͽa =gº·8 Ôe Û]©°Äz8'ñn/«©ÈýôÚ‡ÀH€zI¸±ô|¢ž¶˜xA@Šs øÄþ©°†M5ý/) ²‡j³d'Ý0r¹b+"åhîIuÏŽÕ.ÞXh¦§êÀüj »õ>LÞ”al9^h7w“12±¾m+øIîfŸÓoIÈÁû?nŽ[n®}O,s¯-¦ùƒK›ˆI–ÒTþ-°ë“08Æá¾Àiì‡[îÎû¯ëNdõšD4F9¤„S¢[—¸oWÞè§«I ®Ú?7ã*RȸžìîbúÚ(Qt"\0@ 5¼,û€ ®ß�ŒO[¨ó©¶6ÆP›îð0³(�«Íg™voO¿—€[;qp�·®N‡Š¡ÐMËÕ¸ùêÁ¾Ž°HMf½Á|ê*šôð’ ÄÊWLdLz ÿ¢?²ãQkKI°9Dmqjªd23€ªS¦�‹ÊßkÙ»ñjXU)½ò ’§*5 í¹ë�ŒT+õüiðu/ã×úŠ;pBHD§�—:Õ=K¦ŸAE’a™U>cV¤>;±½°o{ÀoQçr^€�¥Bõ‡! ›‘Îý488,jU{.!½¨µfuHÒÝÇ%{÷XqR¦¯”’49ö€„´.o^ÇçE°¨<¿‡=\ôN¥‡Ç’L?øº*BàÙ}Â]ñýj‚ö)Õÿ %æÙ0tå}±Ã¸¯R+@ÉoÝѺý/) ²‡j³d'Ý0r¹bbÒÌîó΃ÞC _”É'vÍ/ÄtVqy~'èfOò s=Ak4Àn÷�ð�‹UÉT �pnòÇ–¢”€#v…µÓCĹõ Fx£ƒ{Öˆ&è ‡*–û˜æ¥¦¤‹ä‘Ðy¡ç©*¹ÃSà>Ê ë䮽}y½ ùÑ¢Á¼ÔÜ'ÌB¡æ¼&/&½f2êt°o{ÀoQçr^€�¥Bõ‡php-comment"> */ 12: 13: namespace DataTables\Editor; 14: if (!defined('DATATABLES')) exit(); 15: 16: use 17: DataTables, 18: DataTables\Editor, 19: DataTables\Editor\Options, 20: DataTables\Editor\Join; 21: 22: 23: /** 24: * Field definitions for the DataTables Editor. 25: * 26: * Each Database column that is used with Editor can be described with this 27: * Field method (both for Editor and Join instances). It basically tells 28: * Editor what table column to use, how to format the data and if you want 29: * to read and/or write this column. 30: * 31: * Field instances are used with the {@link Editor::field} and 32: * {@link Join::field} methods to describe what fields should be interacted 33: * with by the editable table. 34: * 35: * @example 36: * Simply get a column with the name "city". No validation is performed. 37: * <code> 38: * Field::inst( 'city' ) 39: * </code> 40: * 41: * @example 42: * Get a column with the name "first_name" - when edited a value must 43: * be given due to the "required" validation from the {@link Validate} class. 44: * <code> 45: * Field::inst( 'first_name' )->validator( 'Validate::required' ) 46: * </code> 47: * 48: * @example 49: * Working with a date field, which is validated, and also has *get* and 50: * *set* formatters. 51: * <code> 52: * Field::inst( 'registered_date' ) 53: * ->validator( 'Validate::dateFormat', 'D, d M y' ) 54: * ->getFormatter( 'Format::date_sql_to_format', 'D, d M y' ) 55: * ->setFormatter( 'Format::date_format_to_sql', 'D, d M y' ) 56: * </code> 57: * 58: * @example 59: * Using an alias in the first parameter 60: * <code> 61: * Field::inst( 'name.first as first_name' ) 62: * </code> 63: */ 64: class Field extends DataTables\Ext { 65: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 66: * Statics 67: */ 68: 69: /** Set option flag (`set()`) - do not set data */ 70: const SET_NONE = 'none'; 71: 72: /** Set option flag (`set()`) - write to database on both create and edit */ 73: const SET_BOTH = 'both'; 74: 75: /** Set option flag (`set()`) - write to database only on create */ 76: const SET_CREATE = 'create'; 77: 78: /** Set option flag (`set()`) - write to database only on edit */ 79: const SET_EDIT = 'edit'; 80: 81: 82: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 83: * Constructor 84: */ 85: 86: /** 87: * Field instance constructor. 88: * @param string $dbField Name of the database column 89: * @param string $name Name to use in the JSON output from Editor and the 90: * HTTP submit from the client-side when editing. If not given then the 91: * $dbField name is used. 92: */ 93: function __construct( $dbField=null, $name=null ) 94: { 95: if ( $dbField !== null && $name === null ) { 96: // Allow just a single parameter to be passed - each can be 97: // overridden if needed later using the API. 98: $this->name( $dbField ); 99: $this->dbField( $dbField ); 100: } 101: else { 102: $this->name( $name ); 103: $this->dbField( $dbField ); 104: } 105: } 106: 107: 108: 109: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 110: * Private parameters 111: */ 112: 113: /** @var string */ 114: private $_dbField = null; 115: 116: /** @var boolean */ 117: private $_get = true; 118: 119: /** @var mixed */ 120: private $_getFormatter = null; 121: 122: /** @var mixed */ 123: private $_getFormatterOpts = null; 124: 125: /** @var mixed */ 126: private $_getValue = null; 127: 128: /** @var Options */ 129: private $_opts = null; 130: 131: /** @var SearchPaneOptions */ 132: private $_spopts = null; 133: 134: /** @var callable */ 135: private $_optsFn = null; 136: 137: /** @var callable */ 138: private $_spoptsFn = null; 139: 140: /** @var string */ 141: private $_name = null; 142: 143: /** @var string */ 144: private $_set = Field::SET_BOTH; 145: 146: /** @var mixed */ 147: private $_setFormatter = null; 148: 149: /** @var mixed */ 150: private $_setFormatterOpts = null; 151: 152: /** @var mixed */ 153: private $_setValue = null; 154: 155: /** @var mixed */ 156: private $_validator = array(); 157: 158: /** @var Upload */ 159: private $_upload = null; 160: 161: /** @var callable */ 162: private $_xss = null; 163: 164: /** @var boolean */ 165: private $_xssFormat = true; 166: 167: 168: 169: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 170: * Public methods 171: */ 172: 173: 174: /** 175: * Get / set the DB field name. 176: * 177: * Note that when used as a setter, an alias can be given for the field 178: * using the SQL `as` keyword - for example: `firstName as name`. In this 179: * situation the dbField is set to the field name before the `as`, and the 180: * field's name (`name()`) is set to the name after the ` as `. 181: * 182: * As a result of this, the following constructs have identical 183: * functionality: 184: * 185: * Field::inst( 'firstName as name' ); 186: * Field::inst( 'firstName', 'name' ); 187: * 188: * @param string $_ Value to set if using as a setter. 189: * @return string|self The name of the db field if no parameter is given, 190: * or self if used as a setter. 191: */ 192: public function dbField ( $_=null ) 193: { 194: if ( $_ === null ) { 195: return $this->_dbField; 196: } 197: 198: // Don't split on an `as` inside paraenthesis 199: $a = preg_split( '/ as (?![^\(]*\))/i', $_ ); 200: if ( count($a) > 1 ) { 201: $this->_dbField = trim( $a[0] ); 202: $this->_name = trim( $a[1] ); 203: } 204: else { 205: $this->_dbField = $_; 206: } 207: 208: return $this; 209: } 210: 211: 212: /** 213: * Get / set the 'get' property of the field. 214: * 215: * A field can be marked as write only when setting the get property to false 216: * here. 217: * @param boolean $_ Value to set if using as a setter. 218: * @return boolean|self The get property if no parameter is given, or self 219: * if used as a setter. 220: */ 221: public function get ( $_=null ) 222: { 223: return $this->_getSet( $this->_get, $_ ); 224: } 225: 226: 227: /** 228: * Get formatter for the field's data. 229: * 230: * When the data has been retrieved from the server, it can be passed through 231: * a formatter here, which will manipulate (format) the data as required. This 232: * can be useful when, for example, working with dates and a particular format 233: * is required on the client-side. 234: * 235: * Editor has a number of formatters available with the {@link Format} class 236: * which can be used directly with this method. 237: * @param callable|string $_ Value to set if using as a setter. Can be given as 238: * a closure function or a string with a reference to a function that will 239: * be called with call_user_func(). 240: * @param mixed $opts Variable that is passed through to the get formatting 241: * function - can be useful for passing through extra information such as 242: * date formatting string, or a required flag. The actual options available 243: * depend upon the formatter used. 244: * @return callable|string|self The get formatter if no parameter is given, or 245: * self if used as a setter. 246: */ 247: public function getFormatter ( $_=null, $opts=null ) 248: { 249: if ( $opts !== null ) { 250: $this->_getFormatterOpts = $opts; 251: } 252: return $this->_getSet( $this->_getFormatter, $_ ); 253: } 254: 255: 256: /** 257: * Get / set a get value. If given, then this value is used to send to the 258: * client-side, regardless of what value is held by the database. 259: * 260: * @param callable|string|number $_ Value to set, or no value to use as a 261: * getter 262: * @return callable|string|self Value if used as a getter, or self if used 263: * as a setter. 264: */ 265: public function getValue ( $_=null ) 266: { 267: return $this->_getSet( $this->_getValue, $_ ); 268: } 269: 270: 271: /** 272: * Get / set the 'name' property of the field. 273: * 274: * The name is typically the same as the dbField name, since it makes things 275: * less confusing(!), but it is possible to set a different name for the data 276: * which is used in the JSON returned to DataTables in a 'get' operation and 277: * the field name used in a 'set' operation. 278: * @param string $_ Value to set if using as a setter. 279: * @return string|self The name property if no parameter is given, or self 280: * if used as a setter. 281: */ 282: public function name ( $_=null ) 283: { 284: return $this->_getSet( $this->_name, $_ ); 285: } 286: 287: 288: /** 289: * Get a list of values that can be used for the options list in radio, 290: * select and checkbox inputs from the database for this field. 291: * 292: * Note that this is for simple 'label / value' pairs only. For more complex 293: * data, including pairs that require joins and where conditions, use a 294: * closure to provide a query 295: * 296: * @param string|callable $table Database table name to use to get the 297: * paired data from, or a closure function if providing a method 298: * @param string $value Table column name that contains the pair's 299: * value. Not used if the first parameter is given as a closure 300: * @param string $label Table column name that contains the pair's 301: * label. Not used if the first parameter is given as a closure 302: * @param callable $condition Function that will add `where` 303: * conditions to the query 304: * @param callable $format Function will render each label 305: * @param string $order SQL ordering 306: * @return Field Self for chaining 307: */ 308: public function options ( $table=null, $value=null, $label=null, $condition=null, $format=null, $order=null ) 309: { 310: if ( $table === null ) { 311: return $this->_opts; 312: } 313: 314: // Overloads for backwards compatibility 315: if ( is_a( $table, '\DataTables\Editor\Options' ) ) { 316: // Options class 317: $this->_optsFn = null; 318: $this->_opts = $table; 319: } 320: else if ( is_callable($table) && is_object($table) ) { 321: // Function 322: $this->_opts = null; 323: $this->_optsFn = $table; 324: } 325: else { 326: $this->_optsFn = null; 327: $this->_opts = Options::inst() 328: ->table( $table ) 329: ->value( $value ) 330: ->label( $label ); 331: 332: if ( $condition ) { 333: $this->_opts->where( $condition ); 334: } 335: 336: if ( $format ) { 337: $this->_opts->render( $format ); 338: } 339: 340: if ( $order ) { 341: $this->_opts->order( $order ); 342: } 343: } 344: 345: return $this; 346: } 347: 348: /** 349: * Get a list of values that can be used for the options list in SearchPanes 350: * 351: * @param SearchPaneOptions|callable $spInput SearchPaneOptions instance or a closure function if providing a method 352: * @return self 353: */ 354: public function searchPaneOptions ( $spInput=null ) 355: { 356: if ( $spInput === null ) { 357: return $this->_spopts; 358: } 359: 360: // Overloads for backwards compatibility 361: if ( is_a( $spInput, '\DataTables\Editor\SearchPaneOptions' ) ) { 362: // Options class 363: $this->_spoptsFn = null; 364: $this->_spopts = $spInput; 365: } 366: else if ( is_callable($spInput) && is_object($spInput) ) { 367: // Function 368: $this->_spopts = null; 369: $this->_spoptsFn = $spInput; 370: } 371: 372: return $this; 373: } 374: 375: 376: 377: /** 378: * Get / set the 'set' property of the field. 379: * 380: * A field can be marked as read only using this option, to be set only 381: * during an create or edit action or to be set during both actions. This 382: * provides the ability to have fields that are only set when a new row is 383: * created (for example a "created" time stamp). 384: * @param string|boolean $_ Value to set when the method is being used as a 385: * setter (leave as undefined to use as a getter). This can take the 386: * value of: 387: * 388: * * `true` - Same as `Field::SET_BOTH` 389: * * `false` - Same as `Field::SET_NONE` 390: * * `Field::SET_BOTH` - Set the database value on both create and edit commands 391: * * `Field::SET_NONE` - Never set the database value 392: * * `Field::SET_CREATE` - Set the database value only on create 393: * * `Field::SET_EDIT` - Set the database value only on edit 394: * @return string|self The set property if no parameter is given, or self 395: * if used as a setter. 396: */ 397: public function set ( $_=null ) 398: { 399: if ( $_ === true ) { 400: $_ = Field::SET_BOTH; 401: } 402: else if ( $_ === false ) { 403: $_ = Field::SET_NONE; 404: } 405: 406: return $this->_getSet( $this->_set, $_ ); 407: } 408: 409: 410: /** 411: * Set formatter for the field's data. 412: * 413: * When the data has been retrieved from the server, it can be passed through 414: * a formatter here, which will manipulate (format) the data as required. This 415: * can be useful when, for example, working with dates and a particular format 416: * is required on the client-side. 417: * 418: * Editor has a number of formatters available with the {@link Format} class 419: * which can be used directly with this method. 420: * @param callable|string $_ Value to set if using as a setter. Can be given as 421: * a closure function or a string with a reference to a function that will 422: * be called with call_user_func(). 423: * @param mixed $opts Variable that is passed through to the get formatting 424: * function - can be useful for passing through extra information such as 425: * date formatting string, or a required flag. The actual options available 426: * depend upon the formatter used. 427: * @return callable|string|self The set formatter if no parameter is given, or 428: * self if used as a setter. 429: */ 430: public function setFormatter ( $_=null, $opts=null ) 431: { 432: if ( $opts !== null ) { 433: $this->_setFormatterOpts = $opts; 434: } 435: return $this->_getSet( $this->_setFormatter, $_ ); 436: } 437: 438: 439: /** 440: * Get / set a set value. If given, then this value is used to write to the 441: * database regardless of what data is sent from the client-side. 442: * 443: * @param callable|string|number $_ Value to set, or no value to use as a 444: * getter 445: * @return callable|string|self Value if used as a getter, or self if used 446: * as a setter. 447: */ 448: public function setValue ( $_=null ) 449: { 450: return $this->_getSet( $this->_setValue, $_ ); 451: } 452: 453: 454: /** 455: * Get / set the upload class for this field. 456: * @param Upload $_ Upload class if used as a setter 457: * @return Upload|self Value if used as a getter, or self if used 458: * as a setter. 459: */ 460: public function upload ( $_=null ) 461: { 462: return $this->_getSet( $this->_upload, $_ ); 463: } 464: 465: 466: /** 467: * Get / set the 'validator' of the field. 468: * 469: * The validator can be used to check if any abstract piece of data is valid 470: * or not according to the given rules of the validation function used. 471: * 472: * Multiple validation options can be applied to a field instance by calling 473: * this method multiple times. For example, it would be possible to have a 474: * 'required' validation and a 'maxLength' validation with multiple calls. 475: * 476: * Editor has a number of validation available with the {@link Validate} class 477: * which can be used directly with this method. 478: * @param callable|string $_ Value to set if using as the validation method. 479: * Can be given as a closure function or a string with a reference to a 480: * function that will be called with call_user_func(). 481: * @param mixed $opts Variable that is passed through to the validation 482: * function - can be useful for passing through extra information such as 483: * date formatting string, or a required flag. The actual options available 484: * depend upon the validation function used. 485: * @return callable|string|self The validation method if no parameter is given, 486: * or self if used as a setter. 487: */ 488: public function validator ( $_=null, $opts=null ) 489: { 490: if ( $_ === null ) { 491: return $this->_validator; 492: } 493: else { 494: $this->_validator[] = array( 495: "func" => $_, 496: "opts" => $opts 497: ); 498: } 499: 500: return $this; 501: } 502: 503: 504: /** 505: * Set a formatting method that will be used for XSS checking / removal. 506: * This should be a function that takes a single argument (the value to be 507: * cleaned) and returns the cleaned value. 508: * 509: * Editor will use HtmLawed by default for this operation, which is built 510: * into the software and no additional configuration is required, but a 511: * custom function can be used if you wish to use a different formatter such 512: * as HTMLPurifier. 513: * 514: * If you wish to disable this option (which you would only do if you are 515: * absolutely confident that your validation will pick up on any XSS inputs) 516: * simply provide a closure function that returns the value given to the 517: * function. This is _not_ recommended. 518: * 519: * @param callable|false $xssFormatter XSS cleaner function, use `false` or 520: * `null` to disable XSS cleaning. 521: * @return Field Self for chaining. 522: */ 523: public function xss ( $xssFormatter ) 524: { 525: if ( $xssFormatter === true || $xssFormatter === false || $xssFormatter === null ) { 526: $this->_xssFormat = $xssFormatter; 527: } 528: else { 529: $this->_xss = $xssFormatter; 530: } 531: 532: return $this; 533: } 534: 535: 536: 537: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 538: * Internal methods 539: * Used by the Editor class and not generally for public use 540: */ 541: 542: /** 543: * Check to see if a field should be used for a particular action (get or set). 544: * 545: * Called by the Editor / Join class instances - not expected for general 546: * consumption - internal. 547: * @param string $action Direction that the data is travelling - 'get' is 548: * reading DB data, `create` and `edit` for writing to the DB 549: * @param array $data Data submitted from the client-side when setting. 550: * @return boolean true if the field should be used in the get / set. 551: * @internal 552: */ 553: public function apply ( $action, $data=null ) 554: { 555: if ( $action === 'get' ) { 556: // Get action - can we get this field 557: return $this->_get; 558: } 559: else { 560: // Note that validation must be done on input data before we get here 561: 562: // Create or edit action, are we configured to use this field 563: if ( $action === 'create' && 564: ($this->_set === Field::SET_NONE || $this->_set === Field::SET_EDIT) 565: ) { 566: return false; 567: } 568: else if ( $action === 'edit' && 569: ($this->_set === Field::SET_NONE || $this->_set === Field::SET_CREATE) 570: ) { 571: return false; 572: } 573: 574: // Check it was in the submitted data. If not, then not required 575: // (validation would have failed if it was) and therefore we don't 576: // set it. Check for a value as well, as it can format data from 577: // some other source 578: if ( $this->_setValue === null && ! $this->_inData( $this->name(), $data ) ) { 579: return false; 580: } 581: 582: // In the data set, so use it 583: return true; 584: } 585: } 586: 587: 588: /** 589: * Execute the ipOpts to get the list of options to return to the client- 590: * side 591: * 592: * @param \DataTables\Database $db Database instance 593: * @return Array Array of value / label options for the list 594: * @internal 595: */ 596: public function optionsExec ( $db ) 597: { 598: if ( $this->_optsFn ) { 599: $fn = $this->_optsFn; 600: return $fn(); 601: } 602: else if ( $this->_opts ) { 603: return $this->_opts->exec( $db ); 604: } 605: 606: return false; 607: } 608: 609: /** 610: * Execute the spopts to get the list of options for SearchPanes to return 611: * to the client-side 612: * 613: * @param DataTables\Field $field The field to retrieve the data from 614: * @param DataTables\Editor $editor The editor instance 615: * @param DataTables\DTRequest $http The http request sent to the server 616: * @param DataTables\Field[] $fields All of the fields 617: * @param any $leftJoin Info for a leftJoin if required 618: * @return Promise<IOption[]> | boolean 619: * @internal 620: */ 621: public function searchPaneOptionsExec ( $field, $editor, $http, $fields, $leftJoin) 622: { 623: if ( $this->_spoptsFn ) { 624: $fn = $this->_spoptsFn; 625: return $fn($editor->db(), $editor); 626: } 627: else if ( $this->_spopts ) { 628: return $this->_spopts->exec( $field, $editor, $http, $fields, $leftJoin ); 629: } 630: 631: return false; 632: } 633: 634: 635: /** 636: * Get the value of the field, taking into account if it is coming from the 637: * DB or from a POST. If formatting has been specified for this field, it 638: * will be applied here. 639: * 640: * Called by the Editor / Join class instances - not expected for general 641: * consumption - internal. 642: * @param string $direction Direction that the data is travelling - 'get' is 643: * reading data, and 'set' is writing it to the DB. 644: * @param array $data Data submitted from the client-side when setting or the 645: * data for the row when getting data from the DB. 646: * @return string Value for the field 647: * @internal 648: */ 649: public function val ( $direction, $data ) 650: { 651: if ( $direction === 'get' ) { 652: if ( $this->_getValue !== null ) { 653: $val = $this->_getAssignedValue( $this->_getValue ); 654: } 655: else { 656: // Getting data, so the db field name 657: $val = isset( $data[ $this->_dbField ] ) ? 658: $data[ $this->_dbField ] : 659: null; 660: } 661: 662: return $this->_format( 663: $val, $data, $this->_getFormatter, $this->_getFormatterOpts 664: ); 665: } 666: else { 667: // Sanity check that we aren't operating on a function 668: if ( strpos( $this->dbField(), '(' ) !== false ) { 669: throw new \Exception('Cannot set the value for an SQL function field. These fields are read only.'); 670: } 671: 672: // Setting data, so using from the payload (POST usually) and thus 673: // use the 'name' 674: $val = $this->_setValue !== null ? 675: $this->_getAssignedValue( $this->_setValue ) : 676: $this->_readProp( $this->name(), $data ); 677: 678: // XSS removal / checker 679: if ( $this->_xssFormat ) { 680: $val = $this->xssSafety( $val ); 681: } 682: 683: return $this->_format( 684: $val, $data, $this->_setFormatter, $this->_setFormatterOpts 685: ); 686: } 687: } 688: 689: 690: /** 691: * Check the validity of the field based on the data submitted. Note that 692: * this validation is performed on the wire data - i.e. that which is 693: * submitted, before any setFormatter is run 694: * 695: * Called by the Editor / Join class instances - not expected for general 696: * consumption - internal. 697: * 698: * @param array $data Data submitted from the client-side 699: * @param Editor $editor Editor instance 700: * @param mixed $id Row id that is being validated 701: * @return boolean|string `true` if valid, string with error message if not 702: * @internal 703: */ 704: public function validate ( $data, $editor, $id=null ) 705: { 706: // Three cases for the validator - closure, string or null 707: if ( ! count( $this->_validator ) ) { 708: return true; 709: } 710: 711: $val = $this->_readProp( $this->name(), $data ); 712: $processData = $editor->inData(); 713: $instances = array( 714: 'action' => $processData['action'], 715: 'id' => $id, 716: 'field' => $this, 717: 'editor' => $editor, 718: 'db' => $editor->db() 719: ); 720: 721: for ( $i=0, $ien=count( $this->_validator ) ; $i<$ien ; $i++ ) { 722: $validator = $this->_validator[$i]; 723: 724: // Backwards compatibility 725: if ( is_string( $validator['func'] ) ) { 726: if ( strpos($validator['func'], "Validate::") === 0 ) { 727: $a = explode("::", $validator['func']); 728: 729: // Validate class static methods - they have `Legacy` counter parts that 730: // convert from the old style to the new so the old style options still work. 731: if ( method_exists( "\\DataTables\\Editor\\".$a[0], $a[1].'Legacy' ) ) { 732: $func = call_user_func( "\\DataTables\\Editor\\".$validator['func'].'Legacy', $validator['opts'] ); 733: $res = call_user_func( $func, $val, $data, $this, $instances ); 734: } 735: else { 736: // User style legacy function. Call it directly 737: $func = "\\DataTables\\Editor\\".$validator['func']; 738: $res = call_user_func( $func, $val, $data, $this, $instances ); 739: } 740: } 741: else { 742: // And for cases where a string was used to point to a function, 743: // which was not in the Validate class 744: $res = call_user_func( $validator['func'], $val, $data, $validator['opts'], $instances ); 745: } 746: } 747: else { 748: $func = $validator['func']; 749: $res = $func( $val, $data, $this, $instances ); 750: } 751: 752: // Check if there was a validation error and if so, return it 753: if ( $res !== true ) { 754: return $res; 755: } 756: } 757: 758: // Validation methods all run, must be valid 759: return true; 760: } 761: 762: 763: /** 764: * Write the value for this field to the output array for a read operation 765: * 766: * @param array $out Row output data (to the JSON) 767: * @param mixed $srcData Row input data (raw, from the database) 768: * @internal 769: */ 770: public function write( &$out, $srcData ) 771: { 772: $this->_writeProp( $out, $this->name(), $this->val('get', $srcData) ); 773: } 774: 775: 776: /** 777: * Perform XSS prevention on an input. 778: * 779: * @param mixed $val Value to be escaped 780: * @return string Safe value 781: */ 782: public function xssSafety ( $val ) { 783: $xss = $this->_xss; 784: 785: if ( is_array( $val ) ) { 786: $res = array(); 787: 788: foreach ( $val as $individual ) { 789: $res[] = $xss ? 790: $xss( $individual ) : 791: DataTables\Vendor\Htmlaw::filter( $individual ); 792: } 793: 794: return $res; 795: } 796: 797: return $xss ? 798: $xss( $val ) : 799: DataTables\Vendor\Htmlaw::filter( $val ); 800: } 801: 802: 803: 804: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 805: * Private methods 806: */ 807: 808: /** 809: * Apply a formatter to data. The caller will decide what formatter to apply 810: * (get or set) 811: * 812: * @param mixed $val Value to be formatted 813: * @param mixed $data Full row data 814: * @param callable $formatter Formatting function to be called 815: * @param array $opts Array of options to be passed to the formatter 816: * @return mixed Formatted value 817: */ 818: private function _format( $val, $data, $formatter, $opts ) 819: { 820: // Three cases for the formatter - closure, string or null 821: if ( ! $formatter ) { 822: return $val; 823: } 824: 825: if ( ! is_string( $formatter ) ) { 826: return $formatter( $val, $data, $opts ); 827: } 828: 829: // Backwards compatibility - strings will not be supported in v2 830: if ( strpos($formatter, "Format::") === 0 ) { 831: $a = explode( '::', $formatter ); 832: 833: // Old style Editor formatter - use the legacy functions to 834: // convert to the new style 835: if ( method_exists( "\\DataTables\\Editor\\".$a[0], $a[1].'Legacy' ) ) { 836: $func = call_user_func( "\\DataTables\\Editor\\".$formatter.'Legacy', $opts ); 837: 838: return $func( $val, $data ); 839: } 840: else { 841: // User added old style methods 842: return call_user_func( "\\DataTables\\Editor\\".$formatter, $val, $data, $opts ); 843: } 844: } 845: 846: // User function (string identifier) 847: return call_user_func( $formatter, $val, $data, $opts ); 848: } 849: 850: /** 851: * Get the value from `_[gs]etValue` - taking into account if it is callable 852: * function or not 853: * 854: * @param mixed $val Value to be evaluated 855: * @return mixed Value assigned, or returned from the function 856: */ 857: private function _getAssignedValue ( $val ) 858: { 859: return is_callable($val) && is_object($val) ? 860: $val() : 861: $val; 862: } 863: 864: /** 865: * Check is a parameter is in the submitted data set. This is functionally 866: * the same as the `_readProp()` method, but in this case a binary value 867: * is required to indicate if the value is present or not. 868: * 869: * @param string $name Javascript dotted object name to write to 870: * @param array $data Data source array to read from 871: * @return boolean `true` if present, `false` otherwise 872: * @private 873: */ 874: private function _inData ( $name, $data ) 875: { 876: if ( strpos($name, '.') === false ) { 877: return isset( $data[ $name ] ) ? 878: true : 879: false; 880: } 881: 882: $names = explode( '.', $name ); 883: $inner = $data; 884: 885: for ( $i=0 ; $i<count($names)-1 ; $i++ ) { 886: if ( ! isset( $inner[ $names[$i] ] ) ) { 887: return false; 888: } 889: 890: $inner = $inner[ $names[$i] ]; 891: } 892: 893: return isset( $inner [ $names[count($names)-1] ] ) ? 894: true : 895: false; 896: } 897: } 898: 899: