class-admin.php
544 lines
| 1 | <?php |
| 2 | |
| 3 | namespace SearchRegex\Admin; |
| 4 | |
| 5 | use SearchRegex\Source; |
| 6 | use SearchRegex\Search; |
| 7 | use SearchRegex\Plugin; |
| 8 | |
| 9 | class Admin { |
| 10 | /** |
| 11 | * @var null|Admin |
| 12 | */ |
| 13 | private static ?Admin $instance = null; |
| 14 | |
| 15 | /** |
| 16 | * Initialize the object |
| 17 | * |
| 18 | * @return Admin |
| 19 | */ |
| 20 | public static function init() { |
| 21 | if ( is_null( self::$instance ) ) { |
| 22 | self::$instance = new self(); |
| 23 | } |
| 24 | |
| 25 | return self::$instance; |
| 26 | } |
| 27 | |
| 28 | /** |
| 29 | * Create the admin class |
| 30 | */ |
| 31 | public function __construct() { |
| 32 | add_action( 'admin_menu', [ $this, 'admin_menu' ] ); |
| 33 | add_filter( 'plugin_action_links_' . basename( dirname( SEARCHREGEX_FILE ) ) . '/' . basename( SEARCHREGEX_FILE ), [ $this, 'plugin_settings' ], 10 ); |
| 34 | add_filter( 'searchregex_result_actions', [ $this, 'extra_actions' ], 10, 3 ); |
| 35 | |
| 36 | register_uninstall_hook( SEARCHREGEX_FILE, [ self::class, 'plugin_uninstall' ] ); |
| 37 | } |
| 38 | |
| 39 | /** |
| 40 | * Tidy the plugin up after being uninstalled |
| 41 | * |
| 42 | * @return void |
| 43 | */ |
| 44 | public static function plugin_uninstall() { |
| 45 | Plugin\Settings::init()->delete(); |
| 46 | delete_option( Search\Preset::OPTION_NAME ); |
| 47 | } |
| 48 | |
| 49 | /** |
| 50 | * Plugin is activated. Load the presets file |
| 51 | * |
| 52 | * @return void |
| 53 | */ |
| 54 | public static function plugin_activated() { |
| 55 | } |
| 56 | |
| 57 | /** |
| 58 | * Add plugin settings to plugin page |
| 59 | * |
| 60 | * @param array<string> $links Links. |
| 61 | * @return array<string> |
| 62 | */ |
| 63 | public function plugin_settings( $links ) { |
| 64 | array_unshift( $links, '<a href="' . esc_url( $this->get_plugin_url() ) . '&sub=options">' . __( 'Settings', 'search-regex' ) . '</a>' ); |
| 65 | return $links; |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * Get plugin URL |
| 70 | * |
| 71 | * @return string |
| 72 | */ |
| 73 | private function get_plugin_url() { |
| 74 | return admin_url( 'tools.php?page=' . basename( SEARCHREGEX_FILE ) ); |
| 75 | } |
| 76 | |
| 77 | /** |
| 78 | * Get first page the current user is allowed to see |
| 79 | * |
| 80 | * @return string |
| 81 | */ |
| 82 | private function get_first_available_page_url() { |
| 83 | $pages = Plugin\Capabilities::get_available_pages(); |
| 84 | |
| 85 | if ( count( $pages ) > 0 ) { |
| 86 | return $this->get_plugin_url() . ( $pages[0] === 'search' ? '' : '&sub=' . rawurlencode( $pages[0] ) ); |
| 87 | } |
| 88 | |
| 89 | return admin_url(); |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Insert stuff into the admin head |
| 94 | * |
| 95 | * @return void |
| 96 | */ |
| 97 | public function searchregex_head() { |
| 98 | global $wp_version; |
| 99 | |
| 100 | // Does user have access to this page? |
| 101 | if ( $this->get_current_page() === false ) { |
| 102 | // Redirect to root plugin page |
| 103 | wp_safe_redirect( $this->get_first_available_page_url() ); |
| 104 | die(); |
| 105 | } |
| 106 | |
| 107 | if ( |
| 108 | isset( $_REQUEST['action'] ) && |
| 109 | isset( $_REQUEST['_wpnonce'] ) && |
| 110 | (bool) wp_verify_nonce( $_REQUEST['_wpnonce'], 'wp_rest' ) |
| 111 | ) { |
| 112 | if ( $_REQUEST['action'] === 'rest_api' ) { |
| 113 | $this->set_rest_api( intval( $_REQUEST['rest_api'], 10 ) ); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | $build = SEARCHREGEX_VERSION . '-' . SEARCHREGEX_BUILD; |
| 118 | $preload = $this->get_preload_data(); |
| 119 | $settings = Plugin\Settings::init(); |
| 120 | |
| 121 | $versions = [ |
| 122 | 'Plugin: ' . SEARCHREGEX_VERSION, |
| 123 | 'WordPress: ' . $wp_version . ' (' . ( is_multisite() ? 'multi' : 'single' ) . ')', |
| 124 | 'PHP: ' . phpversion() . ' ' . ini_get( 'memory_limit' ) . ' ' . ini_get( 'max_execution_time' ) . 's', |
| 125 | 'Browser: ' . $this->get_user_agent(), |
| 126 | 'JavaScript: ' . plugin_dir_url( SEARCHREGEX_FILE ) . 'search-regex.js', |
| 127 | 'REST API: ' . $settings->get_rest_api_url(), |
| 128 | ]; |
| 129 | |
| 130 | $vendor_file = plugin_dir_path( SEARCHREGEX_FILE ) . 'build/vendor.asset.php'; |
| 131 | if ( file_exists( $vendor_file ) ) { |
| 132 | $vendor_assets = include $vendor_file; |
| 133 | wp_enqueue_script( 'search-regex-vendor', plugin_dir_url( SEARCHREGEX_FILE ) . 'build/vendor.js', $vendor_assets['dependencies'], $vendor_assets['version'], true ); |
| 134 | } |
| 135 | |
| 136 | $assets = include plugin_dir_path( SEARCHREGEX_FILE ) . 'build/search-regex.asset.php'; |
| 137 | $dependencies = $assets['dependencies']; |
| 138 | if ( file_exists( $vendor_file ) ) { |
| 139 | $dependencies[] = 'search-regex-vendor'; |
| 140 | } |
| 141 | $version = $assets['version']; |
| 142 | |
| 143 | wp_enqueue_script( 'search-regex', plugin_dir_url( SEARCHREGEX_FILE ) . 'build/search-regex.js', $dependencies, $version, true ); |
| 144 | wp_enqueue_style( 'search-regex', plugin_dir_url( SEARCHREGEX_FILE ) . 'build/search-regex.css', [], $version ); |
| 145 | |
| 146 | $pages = Plugin\Capabilities::get_available_pages(); |
| 147 | $caps = Plugin\Capabilities::get_all_capabilities(); |
| 148 | |
| 149 | $is_new = false; |
| 150 | $major_version = implode( '.', array_slice( explode( '.', SEARCHREGEX_VERSION ), 0, 2 ) ); |
| 151 | |
| 152 | // phpcs:ignore |
| 153 | if ( isset( $_GET['page'] ) && $_GET['page'] === 'search-regex.php' && strpos( SEARCHREGEX_VERSION, '-beta' ) === false ) { |
| 154 | $is_new = $settings->is_new_version( $major_version ); |
| 155 | } |
| 156 | |
| 157 | wp_localize_script( |
| 158 | 'search-regex', 'SearchRegexi10n', [ |
| 159 | 'api' => [ |
| 160 | 'WP_API_root' => esc_url_raw( $settings->get_rest_api_url() ), |
| 161 | 'WP_API_nonce' => wp_create_nonce( 'wp_rest' ), |
| 162 | 'site_health' => admin_url( 'site-health.php' ), |
| 163 | 'current' => $settings->get_rest_api(), |
| 164 | 'routes' => $settings->get_available_rest_api(), |
| 165 | ], |
| 166 | 'pluginBaseUrl' => plugins_url( '', SEARCHREGEX_FILE ), |
| 167 | 'pluginRoot' => $this->get_plugin_url(), |
| 168 | 'locale' => implode( '-', array_slice( explode( '-', str_replace( '_', '-', get_locale() ) ), 0, 2 ) ), |
| 169 | 'settings' => $settings->get_as_json(), |
| 170 | 'preload' => $preload, |
| 171 | 'versions' => implode( "\n", $versions ), |
| 172 | 'version' => SEARCHREGEX_VERSION, |
| 173 | 'caps' => [ |
| 174 | 'pages' => $pages, |
| 175 | 'capabilities' => $caps, |
| 176 | ], |
| 177 | 'update_notice' => $is_new ? $major_version : false, |
| 178 | ] |
| 179 | ); |
| 180 | |
| 181 | wp_set_script_translations( 'search-regex', 'search-regex', plugin_dir_path( SEARCHREGEX_FILE ) . 'languages/json/' ); |
| 182 | |
| 183 | $this->add_help_tab(); |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * Get browser agent |
| 188 | * |
| 189 | * @return string |
| 190 | */ |
| 191 | public function get_user_agent() { |
| 192 | $agent = ''; |
| 193 | |
| 194 | if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { |
| 195 | $agent = $_SERVER['HTTP_USER_AGENT']; |
| 196 | } |
| 197 | |
| 198 | return $agent; |
| 199 | } |
| 200 | |
| 201 | /** |
| 202 | * Set REST API |
| 203 | * |
| 204 | * @param int $api API. |
| 205 | * @return void |
| 206 | */ |
| 207 | private function set_rest_api( $api ) { |
| 208 | Plugin\Settings::init()->set_rest_api( intval( $api, 10 ) ); |
| 209 | } |
| 210 | |
| 211 | /** |
| 212 | * Get preloaded data |
| 213 | * |
| 214 | * @return array<string, mixed> |
| 215 | */ |
| 216 | private function get_preload_data() { |
| 217 | $schema = Source\Manager::get_schema(); |
| 218 | $presets = Search\Preset::get_all(); |
| 219 | |
| 220 | return [ |
| 221 | 'sources' => Source\Manager::get_all_grouped(), |
| 222 | 'presets' => $presets, |
| 223 | 'schema' => $schema, |
| 224 | 'labels' => $this->get_preload_labels( $presets ), |
| 225 | ]; |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | * Get the preloaded labels. |
| 230 | * |
| 231 | * @param array<mixed> $presets |
| 232 | * @return array<int, mixed> |
| 233 | */ |
| 234 | private function get_preload_labels( array $presets ) { |
| 235 | $preload = []; |
| 236 | $filters_to_preload = []; |
| 237 | |
| 238 | if ( isset( $_GET['filters'] ) && is_string( $_GET['filters'] ) ) { |
| 239 | $filters = json_decode( stripslashes( $_GET['filters'] ), true ); |
| 240 | |
| 241 | if ( is_array( $filters ) ) { |
| 242 | $filters_to_preload = array_merge( $filters_to_preload, $filters ); |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | foreach ( $presets as $preset ) { |
| 247 | if ( isset( $preset['search']['filters'] ) ) { |
| 248 | $filters_to_preload = array_merge( $filters_to_preload, $preset['search']['filters'] ); |
| 249 | } |
| 250 | |
| 251 | if ( isset( $preset['search']['action'] ) && $preset['search']['action'] === 'modify' && is_array( $preset['search']['actionOption'] ) ) { |
| 252 | $filters_to_preload = array_merge( |
| 253 | $filters_to_preload, |
| 254 | array_map( |
| 255 | fn( $action ) => [ |
| 256 | 'type' => $action['source'], |
| 257 | 'items' => [ |
| 258 | array_merge( |
| 259 | [ 'column' => $action['column'] ], |
| 260 | $action |
| 261 | ), |
| 262 | ], |
| 263 | ], |
| 264 | $preset['search']['actionOption'] |
| 265 | ) |
| 266 | ); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | foreach ( $filters_to_preload as $filter ) { |
| 271 | if ( is_array( $filter ) && isset( $filter['type'] ) && isset( $filter['items'] ) ) { |
| 272 | foreach ( $filter['items'] as $filt ) { |
| 273 | $preload = array_merge( $preload, Source\Manager::get_schema_preload( $filter['type'], $filt ) ); |
| 274 | } |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | return array_values( array_filter( $preload ) ); |
| 279 | } |
| 280 | |
| 281 | /** |
| 282 | * Replace links |
| 283 | * |
| 284 | * @internal |
| 285 | * @param string $text Text to replace. |
| 286 | * @param string $url URL to insert into the link. |
| 287 | * @param string $link Link name. |
| 288 | * @return string |
| 289 | */ |
| 290 | private function linkify( $text, $url, $link = 'link' ) { |
| 291 | return (string) preg_replace( '@{{' . $link . '}}(.*?){{/' . $link . '}}@', '<a target="_blank" rel="noopener noreferrer" href="' . esc_url( $url ) . '">$1</a>', $text ); |
| 292 | } |
| 293 | |
| 294 | /** |
| 295 | * Add help tab |
| 296 | * |
| 297 | * @internal |
| 298 | * @return void |
| 299 | */ |
| 300 | private function add_help_tab() { |
| 301 | $flags = $this->linkify( |
| 302 | $this->linkify( |
| 303 | __( '{{link}}Source Flags{{/link}} - additional options for the selected source. For example, include post {{guid}}GUID{{/guid}} in the search.', 'search-regex' ), |
| 304 | 'https://searchregex.com/support/search-source/' |
| 305 | ), |
| 306 | 'https://deliciousbrains.com/wordpress-post-guids-sometimes-update/', |
| 307 | 'guid' |
| 308 | ); |
| 309 | |
| 310 | /* translators: URL */ |
| 311 | $content = [ '<p>' . sprintf( __( 'You can find full documentation about using Search Regex on the <a href="%s" target="_blank">searchregex.com</a> support site.', 'search-regex' ), 'https://searchregex.com/support/' ) . '</p>' ]; |
| 312 | $content[] = '<p>' . __( 'The following concepts are used by Search Regex:', 'search-regex' ) . '</p>'; |
| 313 | $content[] = '<ul>'; |
| 314 | $content[] = '<li>' . $this->linkify( __( '{{link}}Search Flags{{/link}} - additional qualifiers for your search, to enable case insensitivity, and to enable regular expression support.', 'search-regex' ), 'https://searchregex.com/support/searching/' ) . '</li>'; |
| 315 | $content[] = '<li>' . $this->linkify( __( '{{link}}Regular expression{{/link}} - a way of defining a pattern for text matching. Provides more advanced matches.', 'search-regex' ), 'https://searchregex.com/support/regular-expression/' ) . '</li>'; |
| 316 | $content[] = '<li>' . $this->linkify( __( '{{link}}Source{{/link}} - the source of data you wish to search. For example, posts, pages, or comments.', 'search-regex' ), 'https://searchregex.com/support/search-source/' ) . '</li>'; |
| 317 | $content[] = '<li>' . $flags . '</li>'; |
| 318 | $content[] = '</ul>'; |
| 319 | |
| 320 | $title = __( 'Search Regex Support', 'search-regex' ); |
| 321 | |
| 322 | $current_screen = get_current_screen(); |
| 323 | if ( $current_screen ) { |
| 324 | $current_screen->add_help_tab( |
| 325 | [ |
| 326 | 'id' => 'search-regex', |
| 327 | 'title' => 'Search Regex', |
| 328 | 'content' => "<h2>$title</h2>" . implode( "\n", $content ), |
| 329 | ] |
| 330 | ); |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | /** |
| 335 | * Admin menu |
| 336 | * |
| 337 | * @return void |
| 338 | */ |
| 339 | public function admin_menu() { |
| 340 | $access = Plugin\Capabilities::get_plugin_access(); |
| 341 | $hook = add_management_page( 'Search Regex', 'Search Regex', $access, basename( SEARCHREGEX_FILE ), [ $this, 'admin_screen' ] ); |
| 342 | if ( $hook ) { |
| 343 | add_action( 'load-' . $hook, [ $this, 'searchregex_head' ] ); |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | /** |
| 348 | * Check if we meet minimum WP requirements |
| 349 | * |
| 350 | * @return bool |
| 351 | */ |
| 352 | private function check_minimum_wp() { |
| 353 | $wp_version = get_bloginfo( 'version' ); |
| 354 | |
| 355 | if ( version_compare( $wp_version, SEARCHREGEX_MIN_WP, '<' ) ) { |
| 356 | return false; |
| 357 | } |
| 358 | |
| 359 | return true; |
| 360 | } |
| 361 | |
| 362 | /** |
| 363 | * Admin screen |
| 364 | * |
| 365 | * @return void |
| 366 | */ |
| 367 | public function admin_screen() { |
| 368 | if ( count( Plugin\Capabilities::get_all_capabilities() ) === 0 ) { |
| 369 | die( 'You do not have sufficient permissions to access this page.' ); |
| 370 | } |
| 371 | |
| 372 | if ( $this->check_minimum_wp() === false ) { |
| 373 | $this->show_minimum_wordpress(); |
| 374 | return; |
| 375 | } |
| 376 | |
| 377 | $this->show_main(); |
| 378 | } |
| 379 | |
| 380 | /** |
| 381 | * Show minimum supported WP |
| 382 | * |
| 383 | * @internal |
| 384 | * @return void |
| 385 | */ |
| 386 | private function show_minimum_wordpress() { |
| 387 | global $wp_version; |
| 388 | |
| 389 | /* translators: 1: Expected WordPress version, 2: Actual WordPress version */ |
| 390 | $wp_requirement = sprintf( __( 'Search Regex requires WordPress v%1$1s, you are using v%2$2s - please update your WordPress', 'search-regex' ), SEARCHREGEX_MIN_WP, $wp_version ); |
| 391 | ?> |
| 392 | <div class="react-error"> |
| 393 | <h1><?php esc_html_e( 'Unable to load Search Regex', 'search-regex' ); ?></h1> |
| 394 | <p><?php echo esc_html( $wp_requirement ); ?></p> |
| 395 | </div> |
| 396 | <?php |
| 397 | } |
| 398 | |
| 399 | /** |
| 400 | * Show fail to load page |
| 401 | * |
| 402 | * @internal |
| 403 | * @return void |
| 404 | */ |
| 405 | private function show_load_fail() { |
| 406 | ?> |
| 407 | <div class="react-error" style="display: none"> |
| 408 | <h1><?php esc_html_e( 'Unable to load Search Regex ☹️', 'search-regex' ); ?> v<?php echo esc_html( SEARCHREGEX_VERSION ); ?></h1> |
| 409 | <p><?php esc_html_e( "This may be caused by another plugin - look at your browser's error console for more details.", 'search-regex' ); ?></p> |
| 410 | <p><?php esc_html_e( 'If you are using a page caching plugin or service (CloudFlare, OVH, etc) then you can also try clearing that cache.', 'search-regex' ); ?></p> |
| 411 | <p><?php echo wp_kses( __( 'Also check if your browser is able to load <code>search-regex.js</code>:', 'search-regex' ), [ 'code' => [] ] ); ?></p> |
| 412 | <p><code><?php echo esc_html( plugin_dir_url( SEARCHREGEX_FILE ) . 'build/search-regex.js?ver=' . rawurlencode( SEARCHREGEX_VERSION ) . '-' . rawurlencode( SEARCHREGEX_BUILD ) ); ?></code></p> |
| 413 | <p><?php esc_html_e( 'Please note that Search Regex requires the WordPress REST API to be enabled. If you have disabled this then you won\'t be able to use Search Regex', 'search-regex' ); ?></p> |
| 414 | <p><?php echo wp_kses( __( 'Please see the <a href="https://searchregex.com/support/problems/">list of common problems</a>.', 'search-regex' ), [ 'a' => [ 'href' => [] ] ] ); ?></p> |
| 415 | <p><?php esc_html_e( 'If you think Search Regex is at fault then create an issue.', 'search-regex' ); ?></p> |
| 416 | <p class="versions"><?php echo wp_kses( __( '<code>SearchRegexi10n</code> is not defined. This usually means another plugin is blocking Search Regex from loading. Please disable all plugins and try again.', 'search-regex' ), [ 'code' => [] ] ); ?></p> |
| 417 | <p> |
| 418 | <a class="button-primary" target="_blank" href="https://github.com/johngodley/search-regex/issues/new?title=Problem%20starting%20Search%20Regex%20<?php echo esc_attr( SEARCHREGEX_VERSION ); ?>"> |
| 419 | <?php esc_html_e( 'Create Issue', 'search-regex' ); ?> |
| 420 | </a> |
| 421 | </p> |
| 422 | </div> |
| 423 | <?php |
| 424 | } |
| 425 | |
| 426 | /** |
| 427 | * Show main UI |
| 428 | * |
| 429 | * @internal |
| 430 | * @return void |
| 431 | */ |
| 432 | private function show_main() { |
| 433 | ?> |
| 434 | <div id="react-ui"> |
| 435 | <div class="react-loading"> |
| 436 | <h1><?php esc_html_e( 'Loading, please wait...', 'search-regex' ); ?></h1> |
| 437 | |
| 438 | <span class="react-loading-spinner"></span> |
| 439 | </div> |
| 440 | <noscript><?php esc_html_e( 'Please enable JavaScript', 'search-regex' ); ?></noscript> |
| 441 | |
| 442 | <?php $this->show_load_fail(); ?> |
| 443 | </div> |
| 444 | |
| 445 | <script> |
| 446 | var prevError = window.onerror; |
| 447 | var errors = []; |
| 448 | var timeout = 0; |
| 449 | var timer = setInterval( function() { |
| 450 | if ( isSearchRegexLoaded() ) { |
| 451 | resetAll(); |
| 452 | } else if ( errors.length > 0 || timeout++ === 5 ) { |
| 453 | showError(); |
| 454 | } |
| 455 | }, 5000 ); |
| 456 | |
| 457 | function isSearchRegexLoaded() { |
| 458 | return typeof searchregex !== 'undefined'; |
| 459 | } |
| 460 | |
| 461 | function showError() { |
| 462 | var errorText = ""; |
| 463 | |
| 464 | if ( errors.length > 0 ) { |
| 465 | errorText = "```\n" + errors.join( ',' ) + "\n```\n\n"; |
| 466 | } |
| 467 | |
| 468 | resetAll(); |
| 469 | document.querySelector( '.react-loading' ).style.display = 'none'; |
| 470 | document.querySelector( '.react-error' ).style.display = 'block'; |
| 471 | |
| 472 | if ( typeof SearchRegexi10n !== 'undefined' ) { |
| 473 | document.querySelector( '.versions' ).innerHTML = SearchRegexi10n.versions.replace( /\n/g, '<br />' ); |
| 474 | document.querySelector( '.react-error .button-primary' ).href += '&body=' + encodeURIComponent( errorText ) + encodeURIComponent( SearchRegexi10n.versions ); |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | function resetAll() { |
| 479 | clearInterval( timer ); |
| 480 | window.onerror = prevError; |
| 481 | } |
| 482 | |
| 483 | window.onerror = function( error, url, line ) { |
| 484 | console.error( error ); |
| 485 | errors.push( error + ' ' + url + ' ' + line ); |
| 486 | }; |
| 487 | </script> |
| 488 | <?php |
| 489 | } |
| 490 | |
| 491 | /** |
| 492 | * Get the current plugin page. |
| 493 | * Uses $_GET['sub'] to determine the current page unless a page is supplied. |
| 494 | * |
| 495 | * @param string|bool $page Current page. |
| 496 | * |
| 497 | * @return string|boolean Current page, or false. |
| 498 | */ |
| 499 | private function get_current_page( $page = false ) { |
| 500 | // $_GET['sub'] is validated below |
| 501 | // phpcs:ignore |
| 502 | if ( ! $page ) { |
| 503 | // phpcs:ignore |
| 504 | $page = $_GET['sub'] ?? 'search'; |
| 505 | } |
| 506 | |
| 507 | // Are we allowed to access this page? |
| 508 | if ( in_array( $page, Plugin\Capabilities::get_available_pages(), true ) ) { |
| 509 | // phpcs:ignore |
| 510 | return $page; |
| 511 | } |
| 512 | |
| 513 | return false; |
| 514 | } |
| 515 | |
| 516 | /** |
| 517 | * Get any extra actions that might be needed. |
| 518 | * |
| 519 | * @param array<string, mixed> $actions Actions. |
| 520 | * @param string $type Type. |
| 521 | * @param Search\Result $result Result. |
| 522 | * @return array<string, mixed> |
| 523 | */ |
| 524 | public function extra_actions( array $actions, $type, $result ) { |
| 525 | if ( $type === 'tablepress_table' ) { |
| 526 | $tables = json_decode( get_option( 'tablepress_tables' ), true ); |
| 527 | |
| 528 | if ( is_array( $tables ) && isset( $tables['table_post'] ) && is_array( $tables['table_post'] ) ) { |
| 529 | foreach ( $tables['table_post'] as $id => $post_id ) { |
| 530 | if ( $post_id === $result->get_row_id() ) { |
| 531 | $actions['edit'] = 'admin.php?page=tablepress&action=edit&table_id=' . rawurlencode( $id ); |
| 532 | break; |
| 533 | } |
| 534 | } |
| 535 | } |
| 536 | } |
| 537 | |
| 538 | return $actions; |
| 539 | } |
| 540 | } |
| 541 | |
| 542 | register_activation_hook( SEARCHREGEX_FILE, [ Admin::class, 'plugin_activated' ] ); |
| 543 | add_action( 'init', [ Admin::class, 'init' ] ); // @phpstan-ignore return.void |
| 544 |