77
88namespace Drupal \views_selective_filters \Plugin \views \filter ;
99
10+ use Drupal \Component \Utility \SafeMarkup ;
1011use Drupal \Core \Form \FormStateInterface ;
12+ use Drupal \views \Plugin \views \display \DisplayPluginBase ;
1113use Drupal \views \Plugin \views \filter \InOperator ;
14+ use Drupal \views \ViewExecutable ;
1215use Drupal \views \Views ;
1316
1417/**
@@ -29,6 +32,15 @@ class Selective extends InOperator {
2932
3033 protected static $ results ;
3134
35+ /**
36+ * {@inheritdoc}
37+ */
38+ public function init (ViewExecutable $ view , DisplayPluginBase $ display , array &$ options = NULL ) {
39+ parent ::init ($ view , $ display , $ options );
40+
41+ $ this ->options ['exposed ' ] = TRUE ;
42+ }
43+
3244 /**
3345 * {@inheritdoc}
3446 */
@@ -62,7 +74,6 @@ public function getValueOptions() {
6274 // is to prevent infinite recursive loop.
6375 if (empty ($ this ->view ->selective_oids ) && !empty ($ this ->view ->inited )) {
6476 $ this ->valueOptions = $ this ->getOids ();
65- debug ('called ' );
6677 // TODO: Omit null values in result: they are improperly handled.
6778 // When constructing the query.
6879 $ this ->valueOptions = array_diff_key ($ this ->valueOptions , ['' => NULL ]);
@@ -109,9 +120,8 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
109120 /**
110121 * Checks if two base fields are compatible.
111122 */
112- protected function BaseFieldCompatible ($ base_field1 , $ base_field2 ) {
123+ protected function baseFieldCompatible ($ base_field1 , $ base_field2 ) {
113124 return strpos ($ base_field2 , $ base_field1 ) === 0 ;
114- return preg_match ('/^ ' . $ base_field1 . '/ ' , $ base_field2 );
115125 }
116126
117127 /**
@@ -124,29 +134,28 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
124134 // Filter should always be exposed, show warning.
125135 array_unshift ($ form ['expose_button ' ], array (
126136 'warning ' => array (
127- '#type ' => 'markup ' ,
128- '#markup ' => '<div class="messages warning"> ' . t ('This filter is always exposed to users. ' ) . '</div> ' ,
137+ '#theme ' => 'status_messages ' ,
138+ '#message_list ' => ['warning ' => [t ('This filter is always exposed to users. ' )]],
139+ '#status_headings ' => [
140+ 'status ' => t ('Status message ' ),
141+ 'error ' => t ('Error message ' ),
142+ 'warning ' => t ('Warning message ' ),
143+ ],
129144 )));
130145 // Remove option to unexpose filter. Tried to disable, but did not work.
131146 $ form ['expose_button ' ]['checkbox ' ]['checkbox ' ]['#type ' ] = 'hidden ' ;
132147 unset($ form ['expose_button ' ]['button ' ]);
133148 unset($ form ['expose_button ' ]['markup ' ]);
134149 // Do not allow to check "all values".
135- $ form ['value ' ]['#attributes ' ][ ' disabled ' ] = ' disabled ' ;
150+ $ form ['value ' ]['#access ' ] = FALSE ;
136151 // Cannot group without values.
137152 unset($ form ['group_button ' ]);
138153
139- // Preload handlers, sorts and filters.
140- // This gest cached all along.
141- $ this ->view ->display_handler ->getHandlers ('field ' );
142- $ this ->view ->display_handler ->getHandlers ('sort ' );
143- $ this ->view ->display_handler ->getHandlers ('filter ' );
144-
145154 // Add combo to pick display field for filter.
146155 $ options = [];
147- foreach ($ this ->view ->display_handler ->handlers [ 'field ' ] as $ key => $ handler ) {
148- if ($ this ->BaseFieldCompatible ($ base_field , $ handler ->field )) {
149- $ options [$ handler ->options ['id ' ]] = $ handler -> definition [ ' group ' ] . ' : ' . $ handler -> definition [ ' title ' ] . ' ( ' . $ handler -> label () . ' ) ' ;
156+ foreach ($ this ->view ->display_handler ->getHandlers ( 'field ' ) as $ field ) {
157+ if ($ this ->baseFieldCompatible ($ base_field , $ field ->field )) {
158+ $ options [$ field ->options ['id ' ]] = $ field -> adminLabel () ;
150159 }
151160 }
152161
@@ -218,13 +227,7 @@ public function query() {
218227 if (isset ($ this ->view ->selective_handler_signature ) && $ this ->getSignature () === $ this ->view ->selective_handler_signature ) {
219228 return ;
220229 }
221- // Decode the values to restore special chars.
222- if (is_array ($ this ->value )) {
223- $ this ->value = array_map ('urldecode ' , $ this ->value );
224- }
225- elseif (is_string ($ this ->value )){
226- $ this ->value = urldecode ($ this ->value );
227- }
230+
228231 parent ::query ();
229232 }
230233
@@ -236,14 +239,14 @@ public function query() {
236239 */
237240 protected function getSignature () {
238241 return hash ('sha256 ' , serialize (array (
239- 'name ' => $ this ->view ->name ,
242+ 'id ' => $ this ->view ->id () ,
240243 'args ' => $ this ->view ->args ,
241- 'input ' => $ this ->view ->exposed_input ,
244+ 'input ' => $ this ->view ->getExposedInput () ,
242245 'base_field ' => $ this ->definition ['field_base ' ],
243- 'real_field ' => $ this ->real_field ,
246+ 'real_field ' => $ this ->realField ,
244247 'field ' => $ this ->field ,
245248 'table ' => $ this ->table ,
246- 'ui_name ' => $ this ->options [ ' ui_name ' ] ,
249+ 'ui_name ' => $ this ->adminLabel () ,
247250 )));
248251 }
249252
@@ -253,7 +256,7 @@ protected function getSignature() {
253256 protected function getOids () {
254257 // Parameters that we will be using during the process.
255258 $ base_field = $ this ->definition ['field_base ' ];
256- $ ui_name = $ this ->options [ ' ui_name ' ] ;
259+ $ ui_name = $ this ->adminLabel () ;
257260 $ signature = $ this ->getSignature ();
258261
259262 // Prevent same filters from being recalculated.
@@ -280,54 +283,18 @@ protected function getOids() {
280283 // Limit result set to 100: anything above is not user friendly at all.
281284 $ view_copy ->setItemsPerPage ($ max_items );
282285
283- // Remove paging, and page number from context.
284- if (isset ($ _GET ['items_per_page ' ])) {
285- $ items_per_page = $ _GET ['items_per_page ' ];
286- unset($ _GET ['items_per_page ' ]);
287- }
288- if (isset ($ _GET ['page ' ])) {
289- $ exposed_page = $ _GET ['page ' ];
290- unset($ _GET ['page ' ]);
291- }
292-
293- // Manipulate display + default: don't know if fields are overriden.
294- $ display = $ view_copy ->display [$ this ->view ->current_display ];
295- $ display_default = $ view_copy ->display ['default ' ];
286+ $ view_copy ->setDisplay ($ this ->view ->current_display );
287+ $ display = $ view_copy ->getDisplay ();
296288
297289 // Remove any exposed form configuration. This showed up with BEF module!
298290 unset($ display ->display_options ['exposed_form ' ]);
299- unset($ display_default ->display_options ['exposed_form ' ]);
300291
301- // Also disable attachments.
302- $ display ->handler ->definition ['accept attachments ' ] = FALSE ;
303- $ display_default ->handler ->definition ['accept attachments ' ] = FALSE ;
292+ $ fields =& $ display ->getHandlers ('field ' );
304293
305- // If we are using fields from default or current display.
306- if (isset ($ display ->display_options ['fields ' ])) {
307- $ display_options_fields = &$ display ->display_options ['fields ' ];
308- }
309- else {
310- $ display_options_fields = &$ display_default ->display_options ['fields ' ];
311- }
312-
313- // Original implementation based field matching on ui_name matches
314- // so we need to preserve backwards compatibility.
315- $ field_to_keep = $ this ->options ['selective_display_field ' ];
316-
317- // Remove all fields but the one used to display and aggregate.
318- foreach ($ display_options_fields as $ key => $ value ) {
319- if ($ key !== $ field_to_keep ) {
320- unset($ display_options_fields [$ key ]);
321- }
322- else {
323- // If there is a group column on the field, remove it so Field Collections will work.
324- // https://www.drupal.org/node/2333065
325- unset($ display_options_fields [$ key ]['group_column ' ]);
326- }
327- }
294+ $ fields = array_intersect_key ($ fields , [$ this ->options ['selective_display_field ' ] => TRUE ]);
328295
329296 // Check to see if the user remembered to add the field.
330- if (empty ($ display_options_fields )) {
297+ if (empty ($ fields )) {
331298 drupal_set_message (t ('Selective query filter must have corresponding field added to view with Administrative Name set to "@name" and Base Type "@type" ' ,
332299 array (
333300 '@name ' => $ ui_name ,
@@ -337,17 +304,19 @@ protected function getOids() {
337304 }
338305
339306 // Get ID of field that will be used for rendering.
340- $ display_field = reset ($ display_options_fields );
307+ $ field = reset ($ fields );
308+
309+ $ field_options = $ field ->options ;
341310
342311 // Get field Id.
343- $ display_field_id = $ display_field ['id ' ];
312+ $ field_id = $ field_options ['id ' ];
344313
345314 // Check that relationships are coherent between Field and Filter.
346- $ no_display_field_relationship = empty ($ display_field ['relationship ' ]) || $ display_field ['relationship ' ] === 'none ' ;
315+ $ no_display_field_relationship = empty ($ field_options ['relationship ' ]) || $ field_options ['relationship ' ] === 'none ' ;
347316 $ no_filter_relationship = empty ($ this ->options ['relationship ' ]) || $ this ->options ['relationship ' ] === 'none ' ;
348317 $ equal
349318 = (($ no_display_field_relationship === TRUE ) && ($ no_filter_relationship === TRUE )) ||
350- ($ display_field ['relationship ' ] === $ this ->options ['relationship ' ]);
319+ ($ field_options ['relationship ' ] === $ this ->options ['relationship ' ]);
351320
352321 if (!$ equal ) {
353322 drupal_set_message (t ('Selective filter "@name": relationship of field and filter must match. ' ,
@@ -360,71 +329,43 @@ protected function getOids() {
360329
361330 // If main field is excluded from presentation, bring it back.
362331 // Set group type for handler to populate database relationships in query.
363- $ display_field ['exclude ' ] = 0 ;
364- $ display_field ['group_type ' ] = 'group ' ;
332+ $ field_options ['exclude ' ] = 0 ;
333+ $ field_options ['group_type ' ] = 'group ' ;
365334
366335 // Remove all sorting: sorts must be added to aggregate fields.
367- unset( $ display ->display_options [ ' sorts ' ] );
368- unset( $ display_default -> display_options [ ' sorts ' ]) ;
336+ // $sorts =& $ display->getHandlers('sort' );
337+ // $ sorts = [] ;
369338
370339 // Turn this into an aggregate query.
371- $ display ->display_options ['group_by ' ] = 1 ;
372- $ display ->handler ->options ['group_by ' ] = 1 ;
373-
374- $ display_default ->display_options ['group_by ' ] = 1 ;
375- $ display_default ->handler ->options ['group_by ' ] = 1 ;
340+ $ display ->setOption ('group_by ' , 1 );
376341
377342 // Aggregate is incompatible with distinct and pure distinct.
378343 // At least it does not make sense as it is implemented now.
379- unset($ display_default ->display_options ['query ' ]['options ' ]['distinct ' ]);
380- unset($ display_default ->display_options ['query ' ]['options ' ]['pure_distinct ' ]);
381-
382- unset($ display ->display_options ['query ' ]['options ' ]['distinct ' ]);
383- unset($ display ->display_options ['query ' ]['options ' ]['pure_distinct ' ]);
344+ $ query_options = $ display ->getOption ('query ' );
345+ $ query_options ['options ' ]['distinct ' ] = TRUE ;
346+ $ display ->setOption ('query ' , $ query_options );
384347
385- // Make sure we are not using a pager to prevent unnecessary count(*) queries.
386- $ display ->display_options ['pager ' ] = unserialize ('a:2:{s:4:"type";s:4:"none";s:7:"options";a:1:{s:6:"offset";s:1:"0";}} ' );
387- $ display_default ->display_options ['pager ' ] = unserialize ('a:2:{s:4:"type";s:4:"none";s:7:"options";a:1:{s:6:"offset";s:1:"0";}} ' );
388-
389- // Some style plugins can affect the built query, make sure
390- // we use a reliable field based style plugin.
391- $ display ->display_options ['style_plugin ' ] = 'default ' ;
392- $ display ->display_options ['style_options ' ] = unserialize ('a:4:{s:9:"row_class";s:0:"";s:17:"default_row_class";i:1;s:17:"row_class_special";i:1;s:11:"uses_fields";i:0;} ' );
393- $ display ->display_options ['row_plugin ' ] = 'fields ' ;
394- $ display ->display_options ['row_options ' ] = unserialize ('s:6:"fields"; ' );
348+ // Some style plugins can affect the built query, make sure we use a
349+ // reliable field based style plugin.
350+ $ display ->setOption ('pager ' , ['type ' => 'none ' , 'options ' => []]);
351+ $ display ->setOption ('style ' , ['type ' => 'default ' , 'options ' => []]);
352+ $ display ->setOption ('row ' , ['type ' => 'fields ' , 'options ' => []]);
395353
396354 // Run View.
397355 $ view_copy ->execute ($ this ->view ->current_display );
398356
399- // Restore context parameters for real View.
400- if (isset ($ items_per_page )) {
401- $ _GET ['items_per_page ' ] = $ items_per_page ;
402- }
403- if (isset ($ exposed_page )) {
404- $ _GET ['page ' ] = $ exposed_page ;
405- }
406-
407- // Get Handler after execution.
408- $ display_field_handler = $ view_copy ->field [$ display_field_id ];
409-
410357 // We show human-readable values when case.
411- if (method_exists ($ display_field_handler , 'getValueOptions ' )) {
412- $ display_field_handler ->getValueOptions ();
358+ if (method_exists ($ field , 'getValueOptions ' )) {
359+ $ field ->getValueOptions ();
413360 }
414361
415362 // Create array of objects for selector.
416363 $ oids = [];
417- $ field_alias = isset ($ display_field_handler ->aliases [$ display_field_handler ->real_field ]) ? $ display_field_handler ->aliases [$ display_field_handler ->real_field ] : $ display_field_handler ->table_alias . '_ ' . $ display_field_handler ->real_field ;
418- foreach ($ view_copy ->result as $ index => $ row ) {
419- // $key = $display_field_handler->get_value($row) should be more robust.
420- // But values are sometimes nested arrays, and we need single values.
421- // For the filters.
422- $ key = $ display_field_handler ->get_value ($ row );
423- if (is_array ($ key )) {
424- $ key = $ row ->{$ field_alias };
425- }
426- $ value = strip_tags ($ view_copy ->render_field ($ display_field_id , $ index ));
427- $ oids [$ key ] = empty ($ value ) ? t ('Empty (@key) ' , array ('@key ' => empty ($ key ) ? json_encode ($ key ) : $ key )) : $ value ;
364+ foreach ($ view_copy ->result as $ row ) {
365+ $ key = $ field ->getValue ($ row );
366+ $ key = is_array ($ key ) ? reset ($ key ) : $ key ;
367+ // @todo This double escapes markup.
368+ $ oids [$ key ] = SafeMarkup::checkPlain ($ field ->render ($ row ));
428369 }
429370
430371 // Sort values.
@@ -465,6 +406,7 @@ protected function getOids() {
465406 static ::$ results [$ signature ] = $ oids ;
466407 $ view_copy ->destroy ();
467408 }
409+
468410 return static ::$ results [$ signature ];
469411 }
470412
0 commit comments