PluginProbe ʕ •ᴥ•ʔ
Search Regex / 3.4.3
Search Regex v3.4.3
3.4.3 trunk 1.4.12 1.4.13 1.4.14 1.4.15 1.4.16 2.0 2.0.1 2.1 2.2 2.2.1 2.3 2.3.1 2.3.2 2.3.3 2.4 2.4.1 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1 3.1.1 3.1.2 3.2 3.3 3.3.0 3.3.1 3.4 3.4.1 3.4.2
search-regex / includes / action / class-dynamic-column.php
search-regex / includes / action Last commit date
type 6 days ago class-action.php 6 months ago class-dynamic-column.php 1 month ago
class-dynamic-column.php
240 lines
1 <?php
2
3 namespace SearchRegex\Action;
4
5 use SearchRegex\Sql;
6 use SearchRegex\Schema;
7 use SearchRegex\Source;
8
9 /**
10 * Dynamic data in columns (via shortcodes)
11 */
12 class Dynamic_Column {
13 const LOOP_MAX = 10;
14
15 /**
16 * Array of supported shortcodes
17 *
18 * @var string[]
19 */
20 private array $shortcodes;
21
22 /**
23 * Array of standard WP shortcodes
24 *
25 * @var string[]
26 */
27 private array $old_shortcodes = [];
28
29 /**
30 * Row ID
31 */
32 private int $row_id = 0;
33
34 /**
35 * Row value
36 */
37 private string $row_value = '';
38
39 /**
40 * Raw row data
41 *
42 * @var array<string, mixed>
43 */
44 private array $raw = [];
45
46 /**
47 * Source schema
48 */
49 private ?Schema\Source $schema = null;
50
51 /**
52 * Recursion level protection
53 */
54 private int $level = 0;
55
56 public function __construct() {
57 add_filter( 'searchregex_text', [ $this, 'replace_text' ], 10, 5 );
58
59 $this->shortcodes = apply_filters(
60 'searchregex_shortcodes', [
61 'md5',
62 'upper',
63 'lower',
64 'dashes',
65 'underscores',
66 'column',
67 'value',
68 'date',
69 ]
70 );
71
72 global $shortcode_tags;
73
74 $this->old_shortcodes = $shortcode_tags;
75
76 remove_all_shortcodes();
77
78 foreach ( $this->shortcodes as $code ) {
79 add_shortcode( $code, [ $this, 'do_shortcode' ] );
80 }
81 }
82
83 public function __destruct() {
84 global $shortcode_tags;
85
86 // Restore shortcodes
87 // phpcs:ignore
88 $shortcode_tags = $this->old_shortcodes;
89 }
90
91 /**
92 * Replace shortcodes in a value
93 *
94 * @param string $text Replacement text, including shortcodes.
95 * @param int $row_id Row ID.
96 * @param string $row_value Row value.
97 * @param array<string, mixed> $raw Raw row data.
98 * @param Schema\Source $schema Schema.
99 * @return string
100 */
101 public function replace_text( $text, $row_id, $row_value, array $raw, Schema\Source $schema ) {
102 // Keep track of these in the object
103 $this->row_id = $row_id;
104 $this->row_value = $row_value;
105 $this->raw = $raw;
106 $this->level = 0;
107 $this->schema = $schema;
108
109 return do_shortcode( $text );
110 }
111
112 /**
113 * Peform a shortcode
114 *
115 * @param array<string, mixed>|array<int, string> $attrs Shortcode attributes.
116 * @param string|null $content Shortcode content.
117 * @param string $tag Shortcode tag.
118 * @return string
119 */
120 public function do_shortcode( $attrs, $content, $tag ) {
121 if ( $this->schema === null ) {
122 return '';
123 }
124
125 $named_attrs = [];
126 foreach ( $attrs as $name => $value ) {
127 if ( is_string( $name ) ) {
128 $named_attrs[ $name ] = $value;
129 }
130 }
131
132 $this->level++;
133 if ( $this->level > self::LOOP_MAX ) {
134 return '';
135 }
136
137 switch ( $tag ) {
138 case 'md5':
139 return md5( do_shortcode( $content ?? '' ) );
140
141 case 'upper':
142 return strtoupper( do_shortcode( $content ?? '' ) );
143
144 case 'lower':
145 return strtolower( do_shortcode( $content ?? '' ) );
146
147 case 'dashes':
148 return str_replace( [ '_', ' ' ], '-', do_shortcode( $content ?? '' ) );
149
150 case 'underscores':
151 return str_replace( [ '-', ' ' ], '_', do_shortcode( $content ?? '' ) );
152
153 case 'date':
154 return gmdate( $attrs['format'] ?? 'r' );
155
156 case 'value':
157 return $this->row_value;
158
159 case 'column':
160 $name = '';
161
162 if ( isset( $attrs['name'] ) ) {
163 $name = $attrs['name'];
164 } elseif ( isset( $attrs[0] ) ) {
165 $name = $attrs[0];
166 }
167
168 if ( $name && isset( $this->raw[ $name ] ) ) {
169 $schema = $this->schema->get_column( $name );
170
171 if ( $schema ) {
172 return $this->get_schema_value( $schema, $named_attrs, $this->raw[ $name ] );
173 }
174
175 return $this->raw[ $name ];
176 }
177
178 $schema = $this->schema->get_column( $name );
179 if ( $schema && $schema->get_join_column() ) {
180 return $this->get_schema_join( $schema, $this->row_id, $named_attrs );
181 }
182
183 return '';
184 }
185
186 return apply_filters( 'searchregex_do_shortcode', '', $tag, $attrs, $content );
187 }
188
189 /**
190 * Get schema join
191 *
192 * @param Schema\Column $schema Schema.
193 * @param int $row_id Row ID.
194 * @param array<string, mixed> $attrs Shortcode attributes.
195 * @return string
196 */
197 private function get_schema_join( Schema\Column $schema, $row_id, array $attrs ) {
198 $format = $attrs['format'] ?? 'label';
199
200 if ( $schema->get_column() === 'category' || $schema->get_column() === 'post_tag' ) {
201 $seperator = $attrs['seperator'] ?? ', ';
202 $join = new Sql\Join\Term( $schema->get_column() );
203
204 return $join->get_value( $row_id, $format, $seperator );
205 }
206
207 return '';
208 }
209
210 /**
211 * Get a label from a schema column
212 *
213 * @param Schema\Column $schema Schema.
214 * @param array<string, mixed> $attrs Shortcode attributes.
215 * @param string $row_value Row value.
216 * @return string
217 */
218 private function get_schema_value( Schema\Column $schema, array $attrs, $row_value ) {
219 if ( $schema->get_type() === 'date' && isset( $attrs['format'] ) ) {
220 return gmdate( $attrs['format'], intval( mysql2date( 'U', $row_value ), 10 ) );
221 }
222
223 if ( $schema->get_type() === 'member' && isset( $attrs['format'] ) && $attrs['format'] === 'label' ) {
224 $option = $schema->get_option_label( $row_value );
225
226 if ( $option ) {
227 return $option;
228 }
229 }
230
231 if ( $schema->get_joined_by() !== null || $schema->get_join_column() !== null ) {
232 $convert = new Source\Convert_Values();
233
234 return $convert->convert( $schema, $row_value );
235 }
236
237 return $row_value;
238 }
239 }
240