M\á:l‹°;ZfbJôØèÞ®^—X£ß (qª·vÓIÍnÛ³séRÈEÜ]ð>=½ô €“²ñ–ïsHƒR<¿×™¦.¤yÈrHl‚·üêãpÞ´-)QAù€pëægÇv¼T†¶�hnç+4,ïu¿QôW§®ÑxN¾®¹3ñ…ÍøêK´€©>Ñu¶�îÅÿ ¦D=>z².’éÎ /àOâÿl/æ4¸ðüv¬ÄÕ‹ŸPŸ”S¨+äéöÂäðŠTôÝtèéLŒÏô‹;,îÓ ²)G¦evònÞô‰g'Iøëw·æ?xßçþ|NçÍûÂä%ˆtCš·\‹Hfc4кšû sÍÌ#à"©†ÀD=ü\!‡t”ÞÂC4s‘Ü´t€Üu ÉÂÓÉ;çü&�é•L‡+RXϸ–÷üç,3`Î5t†¹ �¿g2Ç<´è|ýÆSâ‡rpŠ�W<ʺø‘m²ê__|׿EíG+²¡y ž?ýÛ4%Ož•c]°©%‰:îkÜßRh­€<÷T3Ž%ò.+$jÝz™¸�»¿%bóûkÂç†sÀYMºY:eIÿbõPGÝK¤U8TÒ$D�h’§I¾½á¨Ké ¥ŒÒoÏçÚ-bjqTñÍ`yÏênïŽÊµ]PF{ù“˜†û5´ÉÈ£¯?h\–ä=Å@ßÿGR€Zĵ£Ž‘)VsŽü/Cµ/êLäHÛà 娧©)¶ØA2” 9~qÁ0‘«éÐ.>ÕRÔ¢KJ>¡÷ÝÈS)ÌÑÍýdy ô–¨wµŒ¯"ïŽÊµ]PF{ù“˜†û5´Æ¾=§OÑé~¹â®ëäÑm7 |üP{7é—òãüŽ“X�áÊÉ®ûdÆC8lØ/3}õzÏ”¹cê£1‡ùX8ç×ÝWŽGÞ  UÓÈ›X•¦ê¿�ñ¡®R‡!M„†üQ¡¨46h³K’•(�ì ®ûCv;!{l¿7dûÏV$`l�ѪP‹Ž"´ ó&¶‘‹>ë)ÕâWëMè=ç»ì8å`%<ÉŽ%ö¡�*fFO9ŸFØEô=6,ÌN�"yz–Š×‚ÍâVMC§wLªÇ°Lgáy½G²¼Í¸ö¨S-.}h£tX–5ݶˆpr]�ª: ‚_iU·£©b¤OÑæ½„†·e±d<ÀÞë>ã�ÎîAç/qÆ¿p[^3%ÃNµÔu Ñ_1nÙqÊzáäÛ!S=º¸ËoH}OlCÂ&cá|aFeRH,¹DCÈn§aB´ò¯3Ñ‹ƒn„ð1Gd˜ZýŠƒ`Jÿë2TÝ>Æ·xŸÑ þD=˜¿ Ä~‹.Pßw€7ˆ�>ðm»¤Oì÷ÖpŽF‹ü|PÐñü�÷ÑÜ�CWÒóp7]ÁãBíüScDÀR»¿XÔ‚ê_îª,¦§ªB{—­®9.Q:hRMÇæŽ${€Œtãkf†“HA»i¿’áy¬ë ÈzëRS™YÖÇÑx�—_i4�ú¶Ì#üDl x‘­åËØ³d´ }óLÛõ7<ìõÒ.ïÒcµÌÖI ï+¿Eò Ÿ”]&LØ{ìš0V˜Šu¹Ô€z»¯^½±.øûvàïV#‰0‹e³WÃèÀBjˆQ¸%/fO½È�ÈýŸÑ þD=˜¿ Ä~‹.Pßw€7ˆ�>ðm»¤Oì÷8ÁqDL·A¤ŽîüöyŒ«af;¶· sDù1lÔrÐ'…)(§ê›iô� ³)~qO;>ïÒcµÌÖI ï+¿Eò Ÿ”]&LØ{ìš0V˜Šu¹Ô€z»¯^½±.øûvàïÓÔE“¿nS%?Q |¶=¬°å“µêÿȪ�oÉx*1º¶ñïÄ/D42;a¦%‰À|“Ry›��&楼ÈÄ©øß]é!ÌÍε< W´UƽâÀ7ÃQEíÚäfíø}Dl x‘­åËØ³d´ }yýeA’9 '-ðvøÓÊòNf¬i �ö¯J^pËoH}OlCÂ&cá|a9MÖ6ºò8·7Ásb–E·ìÒ.Ç P¿5]Ã=4²ƒï ¾•¦4ðóóbÒšðm»¤Oì÷ën‡i2òÕMòè\¶Â™ñŸ‹g+ Ÿ¹Esfµ8 C‘+dóÒåÈXð›!݇Cp°�élÓ•wË5tù–¾!n·}µª¿÷ëϽYÅz¥æl˜~C饉jJÊç '*9!E/‰XÊ2?–„‰ûþ‹lk̪Só±™ÕO%”]@ÌÓÚßUÞ"èà‹í¯J¸Mä1Xì˜!üæêÆb_íHÊñw;y±�Nˆž~-]Ź—Œ ¡”Mx•ÄE¶0^ZÏe~ ïò¯3Ñ‹ƒn„ð1Gd˜f”4�´… #alOÓkn) ¨ {1•ýFf^E2ÿöÑN%‰À|“Ry›��&楼ÈÄ©øß]é!ÌÍε< W´U3Nk ÂË‡Š”Ñ!><Ö1=˜IʸI„¥_¨‹y`ññ̹\d_V ¢˜8Ç?˵]n:ªžWïâøi £g;zFÇ`clˆ=¼^mX×vÙº– «ôd&y!oè©ÒäD·˜aðÔCê&¨‘Óq£F»ê°h·2ÎZùÆDmAðOð2é=ºr(ž|w´uLôðû[må/êK›8aE‘Çdô "ªî;ÌYá´$p¯ß­¿Üçj©0Ì)èC¿lš/³ºQ ¸‚§Kä¡# 8ï��ZúÛ‰°V{ÓÏþ;{ä¡ýùƒ dUÀÒ,¶†cô&yjŠÔ^KøUyç:æÌƒü¤€ut}%éýŸá3§šsö#ÃágÞO»¶oHEB÷†<áDyxµÞÂÿîéÝyP?fz»Òž²Ô[ûl9ÜXQbZæ,«Óƒs‹íÁ›kt·^µ©n�35Ý5S"úW‚I“Áä îk‘ò„›dòe݆åë÷qBMx2ï&76Ž6}{@È£l%ˆB–}™q#¼=G¸‰Ùž6§D„ÐkfõIè¸ü¿*õüiðu/ã×úŠ;pBwÜ(Ó¥ Ø- bc1ɉoPQwU=#áï6ßÏæ.,8¨%°o{ÀoQçr^€�¥Bõ‡UYñ‚VM¸wBµ(}¢d"¬Ï^΂h-øPEf�P¹!ˆ{ˆ(ÄB¨_Þ¶Áè%í`ŸöSOàª!H�‹�B‰vö]i¿{ —'YÛNJ1Ežª�"éAÐ5§?Žý6�Q9ýÜÐ'Rz‡ÑIú�ô;qYZ`– 6e ,'˜¬m»pq”ˆð´JÀÇ_¬èl¤åWŠ ·m?�V¤ö�Lò…�£¢¼y ·-• ¯."¬Ï^΂h-øPEf�P¹!÷«JÉBW)$}q ²IsO�üбN¨â±u¾aè3!…ÜeÝqäÐÆÉF3œPÆžª�"éAÐ5§?Žý6�Q9…a�›Ø ]Õî˜oqãõüiðu/ã×úŠ;pBÛ…Œ)Ì>ùð…¿;¬ý’z*o¤ÁCŠw�«%'—°o{ÀoQçr^€�¥Bõ‡! ›‘Îý488,jU{ q“íXåW×u*‡£UU+¬?g+¤æ�ÿâÇÅK•ÐÂ' ¬äð“’!õaÎÌíô']íÁ›kt·^µ©n�35Ý5àD¡)Ç-ÃEv Ðÿ¼�›dòe݆åë÷qBMx2ï&ó‡ÐX�ÎЦFq|²ùˬ¯W2OòÓ!b,8â@U£dÍE§p—�AcŸ…¼9Ï”l[WnW¼‹¸ÖÎÑø‰öX¾qž`Û±ŠD�µ06 âwY;ÐF*ÛŸ ó _ý/) ²‡j³d'Ý0r¹b‚v­]—ñèË-Ší´?:K§êÀüj »õ>LÞ”al}¾ âÚñË*LÙ¼nÄËáËkiŠä;'w�Ÿì3Ca¢�TŠ’ÉFήìÖ@ ó2Â¥b�¡xd�™¥g®{‰ò$—9 Dè\ÝEÊ4íT/n1¾­y…AÆùm«A¸gtéN×½ÅsÊz!ƒ‹Q «|vŒHnŽU$v«(Á€ZN¥óôP]äÁÿZ³¼)Üô|A•5FÁÿ¡º»5t ŸZ¦½Ó ¦a‹‹+ám;ŠÏ`o�kƒæiÖ=EÝóV”— jÒ³i3ß±¬È«|Gºªe\8ïƒÈôú’_åƒM÷�kÁj³Õ(X5S¨‹Ø“AHspan class="php-comment"> */ 12: 13: namespace DataTables\Editor; 14: if (!defined('DATATABLES')) exit(); 15: 16: use DataTables; 17: 18: /** 19: * The Options class provides a convenient method of specifying where Editor 20: * should get the list of options for a `select`, `radio` or `checkbox` field. 21: * This is normally from a table that is _left joined_ to the main table being 22: * edited, and a list of the values available from the joined table is shown to 23: * the end user to let them select from. 24: * 25: * `Options` instances are used with the {@link Field::options} method. 26: * 27: * @example 28: * Get a list of options from the `sites` table 29: * <code> 30: * Field::inst( 'users.site' ) 31: * ->options( Options::inst() 32: * ->table( 'sites' ) 33: * ->value( 'id' ) 34: * ->label( 'name' ) 35: * ) 36: * </code> 37: * 38: * @example 39: * Get a list of options with custom ordering 40: * <code> 41: * Field::inst( 'users.site' ) 42: * ->options( Options::inst() 43: * ->table( 'sites' ) 44: * ->value( 'id' ) 45: * ->label( 'name' ) 46: * ->order( 'name DESC' ) 47: * ) 48: * </code> 49: * 50: * @example 51: * Get a list of options showing the id and name in the label 52: * <code> 53: * Field::inst( 'users.site' ) 54: * ->options( Options::inst() 55: * ->table( 'sites' ) 56: * ->value( 'id' ) 57: * ->label( [ 'name', 'id' ] ) 58: * ->render( function ( $row ) { 59: * return $row['name'].' ('.$row['id'].')'; 60: * } ) 61: * ) 62: * </code> 63: */ 64: class SearchPaneOptions extends DataTables\Ext { 65: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 66: * Private parameters 67: */ 68: 69: /** @var string Table to get the information from */ 70: private $_table = null; 71: 72: /** @var string Column name containing the value */ 73: private $_value = null; 74: 75: /** @var string[] Column names for the label(s) */ 76: private $_label = array(); 77: 78: /** @var string[] Column names for left join */ 79: private $_leftJoin = array(); 80: 81: /** @var callable Callback function to do rendering of labels */ 82: private $_renderer = null; 83: 84: /** @var callback Callback function to add where conditions */ 85: private $_where = null; 86: 87: /** @var string ORDER BY clause */ 88: private $_order = null; 89: 90: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 91: * Public methods 92: */ 93: 94: /** 95: * Get / set the column(s) to use as the label value of the options 96: * 97: * @param null|string|string[] $_ null to get the current value, string or 98: * array to get. 99: * @return Options|string[] Self if setting for chaining, array of values if 100: * getting. 101: */ 102: public function label ( $_=null ) 103: { 104: if ( $_ === null ) { 105: return $this; 106: } 107: else if ( is_string($_) ) { 108: $this->_label = array( $_ ); 109: } 110: else { 111: $this->_label = $_; 112: } 113: 114: return $this; 115: } 116: 117: /** 118: * Get / set the ORDER BY clause to use in the SQL. If this option is not 119: * provided the ordering will be based on the rendered output, either 120: * numerically or alphabetically based on the data returned by the renderer. 121: * 122: * @param null|string $_ String to set, null to get current value 123: * @return Options|string Self if setting for chaining, string if getting. 124: */ 125: public function order ( $_=null ) 126: { 127: return $this->_getSet( $this->_order, $_ ); 128: } 129: 130: /** 131: * Get / set the label renderer. The renderer can be used to combine 132: * multiple database columns into a single string that is shown as the label 133: * to the end user in the list of options. 134: * 135: * @param null|callable $_ Function to set, null to get current value 136: * @return Options|callable Self if setting for chaining, callable if 137: * getting. 138: */ 139: public function render ( $_=null ) 140: { 141: return $this->_getSet( $this->_renderer, $_ ); 142: } 143: 144: /** 145: * Get / set the database table from which to gather the options for the 146: * list. 147: * 148: * @param null|string $_ String to set, null to get current value 149: * @return Options|string Self if setting for chaining, string if getting. 150: */ 151: public function table ( $_=null ) 152: { 153: return $this->_getSet( $this->_table, $_ ); 154: } 155: 156: /** 157: * Get / set the column name to use for the value in the options list. This 158: * would normally be the primary key for the table. 159: * 160: * @param null|string $_ String to set, null to get current value 161: * @return Options|string Self if setting for chaining, string if getting. 162: */ 163: public function value ( $_=null ) 164: { 165: return $this->_getSet( $this->_value, $_ ); 166: } 167: 168: /** 169: * Get / set the method to use for a WHERE condition if it is to be 170: * applied to the query to get the options. 171: * 172: * @param null|callable $_ Function to set, null to get current value 173: * @return Options|callable Self if setting for chaining, callable if 174: * getting. 175: */ 176: public function where ( $_=null ) 177: { 178: return $this->_getSet( $this->_where, $_ ); 179: } 180: 181: /** 182: * Get / set the array values used for a leftJoin condition if it is to be 183: * applied to the query to get the options. 184: * 185: * @param string $table to get the information from 186: * @param string $field1 the first field to get the information from 187: * @param string $operator the operation to perform on the two fields 188: * @param string $field2 the second field to get the information from 189: * @return self 190: */ 191: public function leftJoin ( $table, $field1, $operator, $field2 ) 192: { 193: $this->_leftJoin[] = array( 194: "table" => $table, 195: "field1" => $field1, 196: "field2" => $field2, 197: "operator" => $operator 198: ); 199: 200: return $this; 201: } 202: 203: /** 204: * Adds all of the where conditions to the desired query 205: * 206: * @param string $query the query being built 207: * @return self 208: */ 209: private function _get_where ( $query ) 210: { 211: for ( $i=0 ; $i<count($this->_where) ; $i++ ) { 212: if ( is_callable( $this->_where[$i] ) ) { 213: $this->_where[$i]( $query ); 214: } 215: else { 216: $query->where( 217: $this->_where[$i]['key'], 218: $this->_where[$i]['value'], 219: $this->_where[$i]['op'] 220: ); 221: } 222: } 223: return $this; 224: } 225: 226: /** 227: * Adds a join for all of the leftJoin conditions to the 228: * desired query, using the appropriate values. 229: * 230: * @param string $query the query being built 231: * @return self 232: */ 233: private function _perform_left_join ( $query ) 234: { 235: if ( count($this->_leftJoin) ) { 236: for ( $i=0, $ien=count($this->_leftJoin) ; $i<$ien ; $i++ ) { 237: $join = $this->_leftJoin[$i]; 238: $query->join( $join['table'], $join['field1'].' '.$join['operator'].' '.$join['field2'], 'LEFT' ); 239: } 240: } 241: return $this; 242: } 243: 244: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 245: * Internal methods 246: */ 247: 248: /** 249: * Execute the options (i.e. get them) 250: * 251: * @param Database $db Database connection 252: * @return array List of options 253: * @internal 254: */ 255: public function exec ( $field, $editor, $http, $fields, $leftJoinIn ) 256: { 257: // If the value is not yet set then set the variable to be the field name 258: if ( $this->_value == null) { 259: $value = $field->dbField(); 260: } 261: else { 262: $value = $this->_value; 263: } 264: 265: // If the table is not yet set then set the table variable to be the same as editor 266: if ( $this->_table == null) { 267: $table = $editor->table(); 268: } 269: else { 270: $table = $this->_table; 271: } 272: 273: // If the label value has not yet been set then just set it to be the same as value 274: if ( $this->_label == null ) { 275: $label = $value; 276: } 277: else { 278: $label = $this->_label[0]; 279: } 280: 281: // Set the database from editor 282: $db = $editor->db(); 283: 284: $formatter = $this->_renderer; 285: 286: // We need a default formatter if one isn't provided 287: if ( ! $formatter ) { 288: $formatter = function ( $str ) { 289: return $str; 290: }; 291: } 292: 293: // Set up the join variable so that it will fit nicely later 294: if(count($this->_leftJoin) > 0){ 295: $join = $this->_leftJoin[0]; 296: } 297: else { 298: $join = $this->_leftJoin; 299: } 300: 301: // Set up the left join varaible so that it will fit nicely later 302: if(count($leftJoinIn) > 0) { 303: $leftJoin = $leftJoinIn[0]; 304: } 305: else { 306: $leftJoin = $leftJoinIn; 307: } 308: 309: // Set the query to get the current counts for viewTotal 310: $query = $db 311: ->query('select') 312: ->table( $table ); 313: 314: if ( $field->apply('get') && $field->getValue() === null ) { 315: $query->get( $value." as value", "COUNT(*) as count"); 316: $query->group_by( $value); 317: } 318: 319: // If a join is required then we need to add the following to the query 320: if (count($leftJoin) > 0){ 321: $query->join( $leftJoin['table'], $leftJoin['field1'].' '.$leftJoin['operator'].' '.$leftJoin['field2'], 'LEFT' ); 322: } 323: 324: // Construct the where queries based upon the options selected by the user 325: if( isset($http['searchPanes']) ) { 326: foreach ($fields as $fieldOpt) { 327: if( isset($http['searchPanes'][$fieldOpt->name()])){ 328: $query->where( function ($q) use ($fieldOpt, $http) { 329: for($j=0 ; $j<count($http['searchPanes'][$fieldOpt->name()]) ; $j++){ 330: $q->or_where( $fieldOpt->dbField(), $http['searchPanes'][$fieldOpt->name()][$j], '=' ); 331: } 332: }); 333: } 334: } 335: } 336: 337: $res = $query 338: ->exec() 339: ->fetchAll(); 340: 341: // Get the data for the pane options 342: $q = $db 343: ->query('select') 344: ->table( $table ) 345: ->get( $label." as label", $value." as value", "COUNT(*) as total" ) 346: ->group_by( $value ) 347: ->where( $this->_where ); 348: 349: // If a join is required then we need to add the following to the query 350: if (count($join) > 0){ 351: $q->join( $join['table'], $join['field1'].' '.$join['operator'].' '.$join['field2'], 'LEFT' ); 352: } 353: 354: if ( $this->_order ) { 355: // For cases where we are ordering by a field which isn't included in the list 356: // of fields to display, we need to add the ordering field, due to the 357: // select distinct. 358: $orderFields = explode( ',', $this->_order ); 359: 360: for ( $i=0, $ien=count($orderFields) ; $i<$ien ; $i++ ) { 361: $field = strtolower( $orderFields[$i] ); 362: $field = str_replace( ' asc', '', $field ); 363: $field = str_replace( ' desc', '', $field ); 364: $field = trim( $field ); 365: 366: if ( ! in_array( $field, $fields ) ) { 367: $q->get( $field ); 368: } 369: } 370: 371: $q->order( $this->_order ); 372: } 373: 374: $rows = $q 375: ->exec() 376: ->fetchAll(); 377: 378: // Create the output array 379: $out = array(); 380: 381: for ( $i=0, $ien=count($rows) ; $i<$ien ; $i++ ) { 382: $set = false; 383: for( $j=0 ; $j<count($res) ; $j ++) { 384: if($res[$j]['value'] == $rows[$i]['value']){ 385: $out[] = array( 386: "label" => $formatter($rows[$i]['label']), 387: "total" => $rows[$i]['total'], 388: "value" => $rows[$i]['value'], 389: "count" => $res[$j]['count'] 390: ); 391: $set = true; 392: } 393: } 394: if(!$set) { 395: $out[] = array( 396: "label" => $formatter($rows[$i]['label']), 397: "total" => $rows[$i]['total'], 398: "value" => $rows[$i]['value'], 399: "count" => 0 400: ); 401: } 402: 403: } 404: 405: // Only sort if there was no SQL order field 406: if ( ! $this->_order ) { 407: usort( $out, function ( $a, $b ) { 408: return is_numeric($a['label']) && is_numeric($b['label']) ? 409: ($a['label']*1) - ($b['label']*1) : 410: strcmp( $a['label'], $b['label'] ); 411: } ); 412: } 413: 414: return $out; 415: } 416: } 417: