| @@ -6,8 +6,14 @@ | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | namespace ContentControl\RuleEngine; |
| 9 | 9 | |
| 10 | +defined( 'ABSPATH' ) || exit; | |
| 11 | + | |
| 12 | +use ContentControl\Models\RuleEngine\Rule; | |
| 13 | + | |
| 14 | +use function ContentControl\plugin; | |
| 15 | + | |
| 10 | 16 | /** |
| 11 | 17 | * Rules registry |
| 12 | 18 | */ |
| 13 | 19 | class Rules { |
| @@ -14,9 +20,9 @@ | ||
| 14 | 20 | |
| 15 | 21 | /** |
| 16 | 22 | * Array of rules. |
| 17 | 23 | * |
| 18 | - * @var array | |
| 24 | + * @var array<string,array<string,mixed>> | |
| 19 | 25 | */ |
| 20 | 26 | private $data = []; |
| 21 | 27 | |
| 22 | 28 | /** |
| @@ -37,8 +43,9 @@ | ||
| 37 | 43 | return $this->current_rule; |
| 38 | 44 | } |
| 39 | 45 | |
| 40 | 46 | $this->current_rule = $rule; |
| 47 | + return $rule; | |
| 41 | 48 | } |
| 42 | 49 | |
| 43 | 50 | /** |
| 44 | 51 | * Set up rules list. |
| @@ -55,9 +62,9 @@ | ||
| 55 | 62 | |
| 56 | 63 | /** |
| 57 | 64 | * Register new rule type. |
| 58 | 65 | * |
| 59 | - * @param array $rule New rule to register. | |
| 66 | + * @param array<string,mixed> $rule New rule to register. | |
| 60 | 67 | * @return void |
| 61 | 68 | */ |
| 62 | 69 | public function register_rule( $rule ) { |
| 63 | 70 | if ( $this->is_rule_valid( $rule ) ) { |
| @@ -62,8 +69,13 @@ | ||
| 62 | 69 | public function register_rule( $rule ) { |
| 63 | 70 | if ( $this->is_rule_valid( $rule ) ) { |
| 64 | 71 | $rule = wp_parse_args( $rule, $this->get_rule_defaults() ); |
| 65 | 72 | |
| 73 | + /** | |
| 74 | + * Rule index. | |
| 75 | + * | |
| 76 | + * @var string $index | |
| 77 | + */ | |
| 66 | 78 | $index = $rule['name']; |
| 67 | 79 | /** |
| 68 | 80 | * In the case multiple conditions are registered with the same |
| 69 | 81 | * identifier, we append an integer. This do/while quickly increases |
| @@ -84,19 +96,19 @@ | ||
| 84 | 96 | |
| 85 | 97 | /** |
| 86 | 98 | * Check if rule is valid. |
| 87 | 99 | * |
| 88 | - * @param array $rule Rule to test. | |
| 100 | + * @param array<string,mixed> $rule Rule to test. | |
| 89 | 101 | * @return boolean |
| 90 | 102 | */ |
| 91 | 103 | public function is_rule_valid( $rule ) { |
| 92 | - return ! empty( $rule ) && true; | |
| 104 | + return is_array( $rule ) && ! empty( $rule ); | |
| 93 | 105 | } |
| 94 | 106 | |
| 95 | 107 | /** |
| 96 | 108 | * Get array of all registered rules. |
| 97 | 109 | * |
| 98 | - * @return array | |
| 110 | + * @return array<string,array<string,mixed>> | |
| 99 | 111 | */ |
| 100 | 112 | public function get_rules() { |
| 101 | 113 | if ( ! did_action( 'content_control/rule_engine/register_rules' ) ) { |
| 102 | 114 | $this->init(); |
| @@ -108,9 +120,9 @@ | ||
| 108 | 120 | /** |
| 109 | 121 | * Get a rule definition by name. |
| 110 | 122 | * |
| 111 | 123 | * @param string $rule_name Rule definition or null. |
| 112 | - * @return array|null | |
| 124 | + * @return array<string,mixed>|null | |
| 113 | 125 | */ |
| 114 | 126 | public function get_rule( $rule_name ) { |
| 115 | 127 | $rules = $this->get_rules(); |
| 116 | 128 | return isset( $rules[ $rule_name ] ) ? $rules[ $rule_name ] : null; |
| @@ -118,9 +130,9 @@ | ||
| 118 | 130 | |
| 119 | 131 | /** |
| 120 | 132 | * Get array of registered rules filtered for the block-editor. |
| 121 | 133 | * |
| 122 | - * @return array | |
| 134 | + * @return array<string,array<string,mixed>> | |
| 123 | 135 | */ |
| 124 | 136 | public function get_block_editor_rules() { |
| 125 | 137 | $rules = $this->get_rules(); |
| 126 | 138 | |
| @@ -136,12 +148,18 @@ | ||
| 136 | 148 | |
| 137 | 149 | /** |
| 138 | 150 | * Get list of verbs. |
| 139 | 151 | * |
| 140 | - * @return array List of verbs with translatable text. | |
| 152 | + * @return array<string,string> List of verbs with translatable text. | |
| 141 | 153 | */ |
| 142 | 154 | public function get_verbs() { |
| 143 | - return [ | |
| 155 | + static $verbs; | |
| 156 | + | |
| 157 | + if ( isset( $verbs ) ) { | |
| 158 | + return $verbs; | |
| 159 | + } | |
| 160 | + | |
| 161 | + $verbs = [ | |
| 144 | 162 | 'are' => __( 'Are', 'content-control' ), |
| 145 | 163 | 'arenot' => __( 'Are Not', 'content-control' ), |
| 146 | 164 | 'is' => __( 'Is', 'content-control' ), |
| 147 | 165 | 'isnot' => __( 'Is Not', 'content-control' ), |
| @@ -156,16 +174,41 @@ | ||
| 156 | 174 | 'wasnot' => __( 'Was Not', 'content-control' ), |
| 157 | 175 | 'were' => __( 'Were', 'content-control' ), |
| 158 | 176 | 'werenot' => __( 'Were Not', 'content-control' ), |
| 159 | 177 | ]; |
| 178 | + | |
| 179 | + return $verbs; | |
| 160 | 180 | } |
| 161 | 181 | |
| 162 | 182 | /** |
| 183 | + * Get a list of common text strings. | |
| 184 | + * | |
| 185 | + * @return array<string,string> | |
| 186 | + */ | |
| 187 | + protected function get_common_text_strings() { | |
| 188 | + static $text_strings; | |
| 189 | + | |
| 190 | + if ( ! isset( $text_strings ) ) { | |
| 191 | + $text_strings = [ | |
| 192 | + 'User' => __( 'User', 'content-control' ), | |
| 193 | + 'Role(s)' => __( 'Role(s)', 'content-control' ), | |
| 194 | + 'Content' => __( 'Content', 'content-control' ), | |
| 195 | + /* translators: %s: Post type plural name */ | |
| 196 | + 'Select %s' => __( 'Select %s', 'content-control' ), | |
| 197 | + /* translators: %s: Post type singular name */ | |
| 198 | + 'A Selected %s' => __( 'A Selected %s', 'content-control' ), | |
| 199 | + ]; | |
| 200 | + } | |
| 201 | + | |
| 202 | + return $text_strings; | |
| 203 | + } | |
| 204 | + | |
| 205 | + /** | |
| 163 | 206 | * Get a list of built in rules. |
| 164 | 207 | * |
| 165 | 208 | * @return void |
| 166 | 209 | */ |
| 167 | - private function register_built_in_rules() { | |
| 210 | + protected function register_built_in_rules() { | |
| 168 | 211 | $rules = array_merge( |
| 169 | 212 | $this->get_user_rules(), |
| 170 | 213 | $this->get_general_content_rules(), |
| 171 | 214 | $this->get_post_type_rules(), |
| @@ -174,11 +217,11 @@ | ||
| 174 | 217 | |
| 175 | 218 | /** |
| 176 | 219 | * Allow registering additional rules quickly. |
| 177 | 220 | * |
| 178 | - * @param array $rules Rules. | |
| 221 | + * @param array<string,array<string,mixed>> $rules Rules. | |
| 179 | 222 | * |
| 180 | - * @return array | |
| 223 | + * @return array<string,array<string,mixed>> | |
| 181 | 224 | */ |
| 182 | 225 | $rules = apply_filters( 'content_control/rule_engine/rules', $rules ); |
| 183 | 226 | |
| 184 | 227 | foreach ( $rules as $rule ) { |
| @@ -187,9 +230,9 @@ | ||
| 187 | 230 | |
| 188 | 231 | /** |
| 189 | 232 | * Allow manipulating registered rules. |
| 190 | 233 | * |
| 191 | - * @param Rules $this Rules instance. | |
| 234 | + * @param Rules $rules Rules instance. | |
| 192 | 235 | * |
| 193 | 236 | * @return void |
| 194 | 237 | */ |
| 195 | 238 | do_action( 'content_control/rule_engine/register_rules', $this ); |
| @@ -197,18 +240,19 @@ | ||
| 197 | 240 | |
| 198 | 241 | /** |
| 199 | 242 | * Get a list of user rules. |
| 200 | 243 | * |
| 201 | - * @return array | |
| 244 | + * @return array<string,array<string,mixed>> | |
| 202 | 245 | */ |
| 203 | - public function get_user_rules() { | |
| 204 | - $verbs = $this->get_verbs(); | |
| 246 | + protected function get_user_rules() { | |
| 247 | + $verbs = $this->get_verbs(); | |
| 248 | + $strings = $this->get_common_text_strings(); | |
| 205 | 249 | return [ |
| 206 | 250 | 'user_is_logged_in' => [ |
| 207 | 251 | 'name' => 'user_is_logged_in', |
| 208 | 252 | 'label' => __( 'Logged In', 'content-control' ), |
| 209 | 253 | 'context' => [ 'user' ], |
| 210 | - 'category' => __( 'User', 'content-control' ), | |
| 254 | + 'category' => $strings['User'], | |
| 211 | 255 | 'format' => '{category} {verb} {label}', |
| 212 | 256 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 213 | 257 | 'callback' => '\is_user_logged_in', |
| 214 | 258 | ], |
| @@ -213,16 +257,16 @@ | ||
| 213 | 257 | 'callback' => '\is_user_logged_in', |
| 214 | 258 | ], |
| 215 | 259 | 'user_has_role' => [ |
| 216 | 260 | 'name' => 'user_has_role', |
| 217 | - 'label' => __( 'Role(s)', 'content-control' ), | |
| 261 | + 'label' => $strings['Role(s)'], | |
| 218 | 262 | 'context' => [ 'user' ], |
| 219 | - 'category' => __( 'User', 'content-control' ), | |
| 263 | + 'category' => $strings['User'], | |
| 220 | 264 | 'format' => '{category} {verb} {label}', |
| 221 | 265 | 'verbs' => [ $verbs['has'], $verbs['doesnothave'] ], |
| 222 | 266 | 'fields' => [ |
| 223 | 267 | 'roles' => [ |
| 224 | - 'label' => __( 'Role(s)', 'content-control' ), | |
| 268 | + 'label' => $strings['Role(s)'], | |
| 225 | 269 | 'type' => 'tokenselect', |
| 226 | 270 | 'multiple' => true, |
| 227 | 271 | 'options' => wp_roles()->get_names(), |
| 228 | 272 | ], |
| @@ -234,19 +278,20 @@ | ||
| 234 | 278 | |
| 235 | 279 | /** |
| 236 | 280 | * Get a list of general content rules. |
| 237 | 281 | * |
| 238 | - * @return array | |
| 282 | + * @return array<string,array<string,mixed>> | |
| 239 | 283 | */ |
| 240 | - public function get_general_content_rules() { | |
| 241 | - $rules = []; | |
| 242 | - $verbs = $this->get_verbs(); | |
| 284 | + protected function get_general_content_rules() { | |
| 285 | + $rules = []; | |
| 286 | + $verbs = $this->get_verbs(); | |
| 287 | + $strings = $this->get_common_text_strings(); | |
| 243 | 288 | |
| 244 | 289 | $rules['entire_site'] = [ |
| 245 | 290 | 'name' => 'entire_site', |
| 246 | 291 | 'label' => __( 'Entire Site (Any Page, Post, or Archive)', 'content-control' ), |
| 247 | 292 | 'context' => [ 'content' ], |
| 248 | - 'category' => __( 'Content', 'content-control' ), | |
| 293 | + 'category' => $strings['Content'], | |
| 249 | 294 | 'format' => '{category} {verb} {label}', |
| 250 | 295 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 251 | 296 | 'callback' => '__return_true', |
| 252 | 297 | ]; |
| @@ -254,9 +299,9 @@ | ||
| 254 | 299 | $rules['content_is_front_page'] = [ |
| 255 | 300 | 'name' => 'content_is_front_page', |
| 256 | 301 | 'label' => __( 'The Home Page', 'content-control' ), |
| 257 | 302 | 'context' => [ 'content' ], |
| 258 | - 'category' => __( 'Content', 'content-control' ), | |
| 303 | + 'category' => $strings['Content'], | |
| 259 | 304 | 'format' => '{category} {verb} {label}', |
| 260 | 305 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 261 | 306 | 'callback' => '\ContentControl\Rules\content_is_home_page', |
| 262 | 307 | ]; |
| @@ -264,9 +309,9 @@ | ||
| 264 | 309 | $rules['content_is_blog_index'] = [ |
| 265 | 310 | 'name' => 'content_is_blog_index', |
| 266 | 311 | 'label' => __( 'The Blog Index', 'content-control' ), |
| 267 | 312 | 'context' => [ 'content', 'posttype:post' ], |
| 268 | - 'category' => __( 'Content', 'content-control' ), | |
| 313 | + 'category' => $strings['Content'], | |
| 269 | 314 | 'format' => '{category} {verb} {label}', |
| 270 | 315 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 271 | 316 | 'callback' => '\ContentControl\Rules\content_is_blog_index', |
| 272 | 317 | ]; |
| @@ -274,9 +319,9 @@ | ||
| 274 | 319 | $rules['content_is_search_results'] = [ |
| 275 | 320 | 'name' => 'content_is_search_results', |
| 276 | 321 | 'label' => __( 'A Search Result Page', 'content-control' ), |
| 277 | 322 | 'context' => [ 'content', 'search' ], |
| 278 | - 'category' => __( 'Content', 'content-control' ), | |
| 323 | + 'category' => $strings['Content'], | |
| 279 | 324 | 'format' => '{category} {verb} {label}', |
| 280 | 325 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 281 | 326 | 'callback' => '\is_search', |
| 282 | 327 | ]; |
| @@ -284,9 +329,9 @@ | ||
| 284 | 329 | $rules['content_is_404_page'] = [ |
| 285 | 330 | 'name' => 'content_is_404_page', |
| 286 | 331 | 'label' => __( 'A 404 Error Page', 'content-control' ), |
| 287 | 332 | 'context' => [ 'content', '404' ], |
| 288 | - 'category' => __( 'Content', 'content-control' ), | |
| 333 | + 'category' => $strings['Content'], | |
| 289 | 334 | 'format' => '{category} {verb} {label}', |
| 290 | 335 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 291 | 336 | 'callback' => '\is_404', |
| 292 | 337 | ]; |
| @@ -296,18 +341,25 @@ | ||
| 296 | 341 | |
| 297 | 342 | /** |
| 298 | 343 | * Get a list of WP post type rules. |
| 299 | 344 | * |
| 300 | - * @return array | |
| 345 | + * @return array<string,array<string,mixed>> | |
| 301 | 346 | */ |
| 302 | - public function get_post_type_rules() { | |
| 303 | - $verbs = $this->get_verbs(); | |
| 347 | + protected function get_post_type_rules() { | |
| 348 | + $verbs = $this->get_verbs(); | |
| 349 | + $strings = $this->get_common_text_strings(); | |
| 304 | 350 | |
| 351 | + // Skip post types that are not public. | |
| 352 | + $should_skip_private_pt = ! plugin()->get_option( 'includePrivatePostTypes', false ); | |
| 353 | + | |
| 354 | + $args = $should_skip_private_pt ? [ 'public' => true ] : []; | |
| 355 | + | |
| 305 | 356 | $rules = []; |
| 306 | - $post_types = get_post_types( [ 'public' => true ], 'objects' ); | |
| 357 | + $post_types = get_post_types( $args, 'objects' ); | |
| 307 | 358 | |
| 308 | - foreach ( $post_types as $name => $post_type ) { | |
| 359 | + foreach ( $post_types as $post_type ) { | |
| 309 | 360 | $type_rules = []; |
| 361 | + $name = $post_type->name; | |
| 310 | 362 | |
| 311 | 363 | if ( $post_type->has_archive || 'post' === $name ) { |
| 312 | 364 | $type_rules[ "content_is_{$name}_archive" ] = [ |
| 313 | 365 | 'name' => "content_is_{$name}_archive", |
| @@ -326,13 +378,13 @@ | ||
| 326 | 378 | |
| 327 | 379 | $type_rules[ "content_is_selected_{$name}" ] = [ |
| 328 | 380 | 'name' => "content_is_selected_{$name}", |
| 329 | 381 | /* translators: %s: Post type singular name */ |
| 330 | - 'label' => sprintf( __( 'A Selected %s', 'content-control' ), $post_type->labels->singular_name ), | |
| 382 | + 'label' => sprintf( $strings['A Selected %s'], $post_type->labels->singular_name ), | |
| 331 | 383 | 'fields' => [ |
| 332 | 384 | 'selected' => [ |
| 333 | 385 | /* translators: %s: Post type plurals name */ |
| 334 | - 'placeholder' => sprintf( __( 'Select %s.', 'content-control' ), strtolower( $post_type->labels->name ) ), | |
| 386 | + 'placeholder' => sprintf( $strings['Select %s'], strtolower( $post_type->labels->name ) ), | |
| 335 | 387 | 'type' => 'postselect', |
| 336 | 388 | 'post_type' => $name, |
| 337 | 389 | 'multiple' => true, |
| 338 | 390 | ], |
| @@ -360,10 +412,10 @@ | ||
| 360 | 412 | /* translators: %s: Post type plural name */ |
| 361 | 413 | 'label' => sprintf( __( 'A Child of Selected %s', 'content-control' ), $post_type->labels->name ), |
| 362 | 414 | 'fields' => [ |
| 363 | 415 | 'selected' => [ |
| 364 | - /* translators: %s: Post type plural name */ | |
| 365 | - 'placeholder' => sprintf( __( 'Select %s.', 'content-control' ), strtolower( $post_type->labels->name ) ), | |
| 416 | + | |
| 417 | + 'placeholder' => sprintf( $strings['Select %s'], strtolower( $post_type->labels->name ) ), | |
| 366 | 418 | 'type' => 'postselect', |
| 367 | 419 | 'post_type' => $name, |
| 368 | 420 | 'multiple' => true, |
| 369 | 421 | ], |
| @@ -377,9 +429,9 @@ | ||
| 377 | 429 | 'label' => sprintf( __( 'An Ancestor of Selected %s', 'content-control' ), $post_type->labels->name ), |
| 378 | 430 | 'fields' => [ |
| 379 | 431 | 'selected' => [ |
| 380 | 432 | /* translators: %s: Post type plural name */ |
| 381 | - 'placeholder' => sprintf( __( 'Select %s.', 'content-control' ), strtolower( $post_type->labels->name ) ), | |
| 433 | + 'placeholder' => sprintf( $strings['Select %s'], strtolower( $post_type->labels->name ) ), | |
| 382 | 434 | 'type' => 'postselect', |
| 383 | 435 | 'post_type' => $name, |
| 384 | 436 | 'multiple' => true, |
| 385 | 437 | ], |
| @@ -387,30 +439,32 @@ | ||
| 387 | 439 | 'callback' => '\ContentControl\Rules\content_is_ancestor_of_post', |
| 388 | 440 | ]; |
| 389 | 441 | } |
| 390 | 442 | |
| 391 | - $templates = wp_get_theme()->get_page_templates(); | |
| 443 | + if ( 'page' === $name ) { | |
| 444 | + $templates = is_admin() ? wp_get_theme()->get_page_templates() : []; | |
| 392 | 445 | |
| 393 | - if ( 'page' === $name && ! empty( $templates ) ) { | |
| 394 | - $type_rules[ "content_is_{$name}_with_template" ] = [ | |
| 395 | - 'name' => "content_is_{$name}_with_template", | |
| 396 | - /* translators: %s: Post type singular name */ | |
| 397 | - 'label' => sprintf( __( 'A %s With Template', 'content-control' ), $post_type->labels->singular_name ), | |
| 398 | - 'fields' => [ | |
| 399 | - 'selected' => [ | |
| 400 | - 'type' => 'tokenselect', | |
| 401 | - 'multiple' => true, | |
| 402 | - 'options' => array_merge( [ 'default' => __( 'Default', 'content-control' ) ], $templates ), | |
| 446 | + if ( ! empty( $templates ) ) { | |
| 447 | + $type_rules[ "content_is_{$name}_with_template" ] = [ | |
| 448 | + 'name' => "content_is_{$name}_with_template", | |
| 449 | + /* translators: %s: Post type singular name */ | |
| 450 | + 'label' => sprintf( __( 'A %s With Template', 'content-control' ), $post_type->labels->singular_name ), | |
| 451 | + 'fields' => [ | |
| 452 | + 'selected' => [ | |
| 453 | + 'type' => 'tokenselect', | |
| 454 | + 'multiple' => true, | |
| 455 | + 'options' => array_merge( [ 'default' => __( 'Default', 'content-control' ) ], $templates ), | |
| 456 | + ], | |
| 403 | 457 | ], |
| 404 | - ], | |
| 405 | - 'callback' => '\ContentControl\Rules\content_is_post_with_template', | |
| 406 | - ]; | |
| 458 | + 'callback' => '\ContentControl\Rules\content_is_post_with_template', | |
| 459 | + ]; | |
| 460 | + } | |
| 407 | 461 | } |
| 408 | 462 | |
| 409 | 463 | foreach ( $type_rules as $rule ) { |
| 410 | 464 | // Merge defaults. |
| 411 | 465 | $type_rules[ $rule['name'] ] = wp_parse_args( $rule, [ |
| 412 | - 'category' => __( 'Content', 'content-control' ), | |
| 466 | + 'category' => $strings['Content'], | |
| 413 | 467 | 'context' => [ 'content', "posttype:{$name}" ], |
| 414 | 468 | 'format' => '{category} {verb} {label}', |
| 415 | 469 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 416 | 470 | 'fields' => [], |
| @@ -419,8 +473,18 @@ | ||
| 419 | 473 | ], |
| 420 | 474 | ] ); |
| 421 | 475 | } |
| 422 | 476 | |
| 477 | + /** | |
| 478 | + * Allow filtering post type rules. | |
| 479 | + * | |
| 480 | + * @param array<string,array<string,mixed>> $type_rules Post type rules. | |
| 481 | + * @param string $name Post type name. | |
| 482 | + * | |
| 483 | + * @return array<string,array<string,mixed>> | |
| 484 | + */ | |
| 485 | + $type_rules = apply_filters( 'content_control/rule_engine/post_type_rules', $type_rules, $name, $post_type ); | |
| 486 | + | |
| 423 | 487 | // Merge type rules & type tax rules. |
| 424 | 488 | $rules = array_merge( $rules, $type_rules, $this->get_post_type_tax_rules( $name ) ); |
| 425 | 489 | } |
| 426 | 490 | |
| @@ -431,30 +495,50 @@ | ||
| 431 | 495 | * Generate post type taxonomy rules. |
| 432 | 496 | * |
| 433 | 497 | * @param string $name Post type name. |
| 434 | 498 | * |
| 435 | - * @return array | |
| 499 | + * @return array<string,array<string,mixed>> | |
| 436 | 500 | */ |
| 437 | - public function get_post_type_tax_rules( $name ) { | |
| 438 | - $verbs = $this->get_verbs(); | |
| 501 | + protected function get_post_type_tax_rules( $name ) { | |
| 502 | + $verbs = $this->get_verbs(); | |
| 503 | + $strings = $this->get_common_text_strings(); | |
| 439 | 504 | |
| 440 | - $post_type = get_post_type_object( $name ); | |
| 441 | - $taxonomies = get_object_taxonomies( $name, 'object' ); | |
| 505 | + $post_type = get_post_type_object( $name ); | |
| 506 | + /** | |
| 507 | + * Taxnomies array. | |
| 508 | + * | |
| 509 | + * @var \WP_Taxonomy[] | |
| 510 | + */ | |
| 511 | + $taxonomies = get_object_taxonomies( $name, 'objects' ); | |
| 442 | 512 | $rules = []; |
| 443 | 513 | |
| 514 | + // Skip taxonomies that are not public. | |
| 515 | + $should_skip_private_tax = ! plugin()->get_option( 'includePrivateTaxonomies', false ); | |
| 516 | + | |
| 444 | 517 | foreach ( $taxonomies as $tax_name => $taxonomy ) { |
| 518 | + if ( $should_skip_private_tax && ! $taxonomy->public ) { | |
| 519 | + continue; | |
| 520 | + } | |
| 521 | + | |
| 445 | 522 | $rules[ "content_is_{$name}_with_{$tax_name}" ] = [ |
| 446 | 523 | 'name' => "content_is_{$name}_with_{$tax_name}", |
| 447 | - /* translators: %1$s: Post type singular name, %2$s: Taxonomy singular name */ | |
| 448 | - 'label' => sprintf( _x( 'A %1$s with %2$s', 'condition: post type plural and taxonomy singular label ie. A Post With Category', 'content-control' ), $post_type->labels->singular_name, $taxonomy->labels->singular_name ), | |
| 524 | + 'label' => sprintf( | |
| 525 | + /* translators: %1$s: Post type singular name, %2$s: Taxonomy singular name */ | |
| 526 | + _x( 'A %1$s with %2$s', 'condition: post type plural and taxonomy singular label ie. A Post With Category', 'content-control' ), | |
| 527 | + $post_type->labels->singular_name, | |
| 528 | + $taxonomy->labels->singular_name | |
| 529 | + ), | |
| 449 | 530 | 'context' => [ 'content', "posttype:{$name}", "taxonomy:{$tax_name}" ], |
| 450 | - 'category' => __( 'Content', 'content-control' ), | |
| 531 | + 'category' => $strings['Content'], | |
| 451 | 532 | 'format' => '{category} {verb} {label}', |
| 452 | 533 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 453 | 534 | 'fields' => [ |
| 454 | 535 | 'selected' => [ |
| 455 | - /* translators: %s: Taxonomy singular name */ | |
| 456 | - 'placeholder' => sprintf( _x( 'Select %s.', 'condition: post type plural label ie. Select categories', 'content-control' ), strtolower( $taxonomy->labels->name ) ), | |
| 536 | + 'placeholder' => sprintf( | |
| 537 | + /* translators: %s: Taxonomy singular name */ | |
| 538 | + $strings['Select %s'], | |
| 539 | + strtolower( $taxonomy->labels->name ) | |
| 540 | + ), | |
| 457 | 541 | 'type' => 'taxonomyselect', |
| 458 | 542 | 'taxonomy' => $tax_name, |
| 459 | 543 | 'multiple' => true, |
| 460 | 544 | ], |
| @@ -466,8 +550,18 @@ | ||
| 466 | 550 | 'callback' => '\ContentControl\Rules\content_is_post_with_tax_term', |
| 467 | 551 | ]; |
| 468 | 552 | } |
| 469 | 553 | |
| 554 | + /** | |
| 555 | + * Allow filtering post type taxonomy rules. | |
| 556 | + * | |
| 557 | + * @param array<string,array<string,mixed>> $rules Post type taxonomy rules. | |
| 558 | + * @param string $name Post type name. | |
| 559 | + * | |
| 560 | + * @return array<string,array<string,mixed>> | |
| 561 | + */ | |
| 562 | + $rules = apply_filters( 'content_control/rule_engine/post_type_tax_rules', $rules, $name ); | |
| 563 | + | |
| 470 | 564 | return $rules; |
| 471 | 565 | } |
| 472 | 566 | |
| 473 | 567 | /** |
| @@ -472,18 +566,24 @@ | ||
| 472 | 566 | |
| 473 | 567 | /** |
| 474 | 568 | * Generates conditions for all public taxonomies. |
| 475 | 569 | * |
| 476 | - * @return array | |
| 570 | + * @return array<string,array<string,mixed>> | |
| 477 | 571 | */ |
| 478 | - public function get_taxonomy_rules() { | |
| 572 | + protected function get_taxonomy_rules() { | |
| 573 | + // Skip taxonomies that are not public. | |
| 574 | + $should_skip_private_tax = ! plugin()->get_option( 'includePrivateTaxonomies', false ); | |
| 575 | + | |
| 576 | + $args = $should_skip_private_tax ? [ 'public' => true ] : []; | |
| 577 | + | |
| 479 | 578 | $rules = []; |
| 480 | - $taxonomies = get_taxonomies( [ 'public' => true ], 'objects' ); | |
| 579 | + $taxonomies = get_taxonomies( $args, 'objects' ); | |
| 481 | 580 | $verbs = $this->get_verbs(); |
| 581 | + $strings = $this->get_common_text_strings(); | |
| 482 | 582 | |
| 483 | 583 | foreach ( $taxonomies as $tax_name => $taxonomy ) { |
| 484 | 584 | $tax_defaults = [ |
| 485 | - 'category' => __( 'Content', 'content-control' ), | |
| 585 | + 'category' => $strings['Content'], | |
| 486 | 586 | 'context' => [ 'content', "taxonomy:{$tax_name}" ], |
| 487 | 587 | 'format' => '{category} {verb} {label}', |
| 488 | 588 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 489 | 589 | 'fields' => [], |
| @@ -501,13 +601,12 @@ | ||
| 501 | 601 | |
| 502 | 602 | $rules[ "content_is_selected_tax_{$tax_name}" ] = wp_parse_args( [ |
| 503 | 603 | 'name' => "content_is_selected_tax_{$tax_name}", |
| 504 | 604 | /* translators: %s: Taxonomy plural name */ |
| 505 | - 'label' => sprintf( _x( 'A Selected %s', 'condition: taxonomy plural label ie. A Selected Category', 'content-control' ), $taxonomy->labels->singular_name ), | |
| 605 | + 'label' => sprintf( $strings['A Selected %s'], $taxonomy->labels->singular_name ), | |
| 506 | 606 | 'fields' => [ |
| 507 | 607 | 'selected' => [ |
| 508 | - /* translators: %s: Taxonomy plural name */ | |
| 509 | - 'placeholder' => sprintf( _x( 'Select %s.', 'condition: taxonomy plural label ie. Select Categories', 'content-control' ), strtolower( $taxonomy->labels->name ) ), | |
| 608 | + 'placeholder' => sprintf( $strings['Select %s'], strtolower( $taxonomy->labels->name ) ), | |
| 510 | 609 | 'type' => 'taxonomyselect', |
| 511 | 610 | 'taxonomy' => $tax_name, |
| 512 | 611 | 'multiple' => true, |
| 513 | 612 | ], |
| @@ -535,17 +634,25 @@ | ||
| 535 | 634 | |
| 536 | 635 | /** |
| 537 | 636 | * Get an array of rule default values. |
| 538 | 637 | * |
| 539 | - * @return array Array of rule default values. | |
| 638 | + * @return array<string,mixed> Array of rule default values. | |
| 540 | 639 | */ |
| 541 | 640 | public function get_rule_defaults() { |
| 542 | - $verbs = $this->get_verbs(); | |
| 543 | - return [ | |
| 641 | + static $rule_defaults; | |
| 642 | + | |
| 643 | + if ( isset( $rule_defaults ) ) { | |
| 644 | + return $rule_defaults; | |
| 645 | + } | |
| 646 | + | |
| 647 | + $verbs = $this->get_verbs(); | |
| 648 | + $strings = $this->get_common_text_strings(); | |
| 649 | + | |
| 650 | + $rule_defaults = [ | |
| 544 | 651 | 'name' => '', |
| 545 | 652 | 'label' => '', |
| 546 | 653 | 'context' => [], |
| 547 | - 'category' => __( 'Content', 'content-control' ), | |
| 654 | + 'category' => $strings['Content'], | |
| 548 | 655 | 'format' => '{category} {verb} {label}', |
| 549 | 656 | 'verbs' => [ $verbs['is'], $verbs['isnot'] ], |
| 550 | 657 | 'fields' => [], |
| 551 | 658 | 'callback' => null, |
| @@ -550,8 +657,10 @@ | ||
| 550 | 657 | 'fields' => [], |
| 551 | 658 | 'callback' => null, |
| 552 | 659 | 'frontend' => false, |
| 553 | 660 | ]; |
| 661 | + | |
| 662 | + return $rule_defaults; | |
| 554 | 663 | } |
| 555 | 664 | |
| 556 | 665 | /** |
| 557 | 666 | * Register & remap deprecated conditions to rules. |
| @@ -557,9 +666,9 @@ | ||
| 557 | 666 | * Register & remap deprecated conditions to rules. |
| 558 | 667 | * |
| 559 | 668 | * @return void |
| 560 | 669 | */ |
| 561 | - public function register_deprecated_rules() { | |
| 670 | + protected function register_deprecated_rules() { | |
| 562 | 671 | /** |
| 563 | 672 | * Filters the old conditions to be registered as rules. |
| 564 | 673 | * |
| 565 | 674 | * @deprecated 2.0.0 |
| @@ -567,9 +676,9 @@ | ||
| 567 | 676 | * @param array $old_rules Array of old rules to manipulate. |
| 568 | 677 | * |
| 569 | 678 | * @return array |
| 570 | 679 | */ |
| 571 | - $old_rules = apply_filters( 'content_control/old_conditions', [] ); | |
| 680 | + $old_rules = apply_filters( 'content_control/rule_engine/deprecated_rules', [] ); | |
| 572 | 681 | |
| 573 | 682 | if ( ! empty( $old_rules ) ) { |
| 574 | 683 | $old_rules = $this->parse_old_rules( $old_rules ); |
| 575 | 684 | |
| @@ -582,10 +691,10 @@ | ||
| 582 | 691 | |
| 583 | 692 | /** |
| 584 | 693 | * Parse rules that are still registered using the older deprecated methods. |
| 585 | 694 | * |
| 586 | - * @param array $old_rules Array of old rules to manipulate. | |
| 587 | - * @return array | |
| 695 | + * @param array<string,mixed> $old_rules Array of old rules to manipulate. | |
| 696 | + * @return array<string,mixed> | |
| 588 | 697 | */ |
| 589 | 698 | public function parse_old_rules( $old_rules ) { |
| 590 | 699 | $new_rules = []; |
| 591 | 700 | |
| @@ -598,10 +707,10 @@ | ||
| 598 | 707 | |
| 599 | 708 | /** |
| 600 | 709 | * Remaps keys & values from an old `condition` into a new `rule`. |
| 601 | 710 | * |
| 602 | - * @param array $old_rule Old rule definition. | |
| 603 | - * @return array New rule definition. | |
| 711 | + * @param array<string,mixed> $old_rule Old rule definition. | |
| 712 | + * @return array<string,mixed> New rule definition. | |
| 604 | 713 | */ |
| 605 | 714 | public function remap_old_rule( $old_rule ) { |
| 606 | 715 | $old_rule = wp_parse_args( $old_rule, $this->get_old_rule_defaults() ); |
| 607 | 716 | |
| @@ -632,9 +741,9 @@ | ||
| 632 | 741 | |
| 633 | 742 | /** |
| 634 | 743 | * Get an array of old rule default values. |
| 635 | 744 | * |
| 636 | - * @return array Array of old rule default values. | |
| 745 | + * @return array<string,mixed> Array of old rule default values. | |
| 637 | 746 | */ |
| 638 | 747 | private function get_old_rule_defaults() { |
| 639 | 748 | return [ |
| 640 | 749 | 'id' => '', |