-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Show settings link & API Key in Network Admin sites list (#583)
- Loading branch information
Showing
6 changed files
with
315 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
<?php | ||
/** | ||
* Parsely Network Admin Site List class | ||
* | ||
* @package Parsely | ||
* @since 3.2.0 | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Parsely\UI; | ||
|
||
use Parsely\Parsely; | ||
use WP_Site; | ||
|
||
/** | ||
* Render the additions to the WordPress Multisite Network Admin Sites List page | ||
* | ||
* @since 3.2.0 | ||
*/ | ||
final class Network_Admin_Sites_List { | ||
const COLUMN_NAME = 'parsely-api-key'; | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @param Parsely $parsely Instance of Parsely class. | ||
*/ | ||
public function __construct( Parsely $parsely ) { | ||
$this->parsely = $parsely; | ||
} | ||
|
||
/** | ||
* Attach network admin page functionality to the appropriate action and filter hooks. | ||
* | ||
* @since 3.2.0 | ||
* @return void | ||
*/ | ||
public function run(): void { | ||
add_filter( 'manage_sites_action_links', array( __CLASS__, 'add_action_link' ), 10, 2 ); | ||
add_filter( 'wpmu_blogs_columns', array( __CLASS__, 'add_api_key_column' ) ); | ||
add_action( 'manage_sites_custom_column', array( $this, 'populate_api_key_column' ), 10, 2 ); | ||
} | ||
|
||
/** | ||
* Use the manage_sites_action_links filter to append a link to the settings page in the "row actions." | ||
* | ||
* @since 3.2.0 | ||
* | ||
* @param array $actions The list of actions meant to be displayed for the current site's context in the row actions. | ||
* @param int $_blog_id The blog ID for the current context. | ||
* @return array The list of actions including ours. | ||
*/ | ||
public static function add_action_link( array $actions, int $_blog_id ): array { | ||
if ( ! current_user_can( Parsely::CAPABILITY ) ) { | ||
return $actions; | ||
} | ||
|
||
$actions['parsely-settings'] = sprintf( | ||
'<a href="%1$s" aria-label="%2$s">%3$s</a>', | ||
esc_url( esc_url( Parsely::get_settings_url( $_blog_id ) ) ), | ||
esc_attr( self::generate_aria_label_for_blog_id( $_blog_id ) ), | ||
__( 'Parse.ly Settings', 'wp-parsely' ) | ||
); | ||
|
||
return $actions; | ||
} | ||
|
||
/** | ||
* Generate ARIA label content. | ||
* | ||
* @since 3.2.0 | ||
* | ||
* @param int $_blog_id Which sub-site to include in the ARIA label. | ||
* @return string ARIA label content including the blogname. | ||
*/ | ||
private static function generate_aria_label_for_blog_id( int $_blog_id ): string { | ||
$site = get_blog_details( $_blog_id ); | ||
|
||
return sprintf( | ||
/* translators: blog name or blog id if empty */ | ||
__( 'Go to Parse.ly stats for "%s"', 'wp-parsely' ), | ||
empty( $site->blogname ) ? $_blog_id : $site->blogname | ||
); | ||
} | ||
|
||
/** | ||
* Use the wpmu_blogs_columns filter to register the column where we'll display the site's API Key (if configured). | ||
* | ||
* @since 3.2.0 | ||
* | ||
* @param array $sites_columns The list of columns meant to be displayed in the sites list table. | ||
* @return array The list of columns to display in the network admin table including ours. | ||
*/ | ||
public static function add_api_key_column( array $sites_columns ): array { | ||
$sites_columns[ self::COLUMN_NAME ] = __( 'Parse.ly API Key', 'wp-parsely' ); | ||
return $sites_columns; | ||
} | ||
|
||
/** | ||
* Use the manage_sites_custom_column action to output each site's API Key (if configured). | ||
* | ||
* @since 3.2.0 | ||
* | ||
* @param string $column_name The column name for the current context. | ||
* @param int $_blog_id The blog ID for the current context. | ||
* @return void | ||
*/ | ||
public function populate_api_key_column( string $column_name, int $_blog_id ): void { | ||
if ( self::COLUMN_NAME !== $column_name ) { | ||
return; | ||
} | ||
|
||
// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.switch_to_blog_switch_to_blog | ||
switch_to_blog( $_blog_id ); | ||
$apikey = $this->parsely->get_api_key(); | ||
restore_current_blog(); | ||
|
||
if ( strlen( $apikey ) > 0 ) { | ||
echo esc_html( $apikey ); | ||
} else { | ||
echo '<em>' . esc_html__( 'Parse.ly API key is missing', 'wp-parsely' ) . '</em>'; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<?php | ||
/** | ||
* UI Tests for the Network Admin Sites List. | ||
* | ||
* @package Parsely | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Parsely\Tests\Integration\UI; | ||
|
||
use Parsely\Parsely; | ||
use Parsely\Tests\Integration\TestCase; | ||
use Parsely\UI\Network_Admin_Sites_List; | ||
use WP_Site; | ||
|
||
/** | ||
* UI Tests for the Network Admin Sites List. | ||
*/ | ||
final class NetworkAdminSitesListTest extends TestCase { | ||
/** | ||
* Hold an insance of Network_Admin_Sites_List | ||
* | ||
* @var Network_Admin_Sites_List | ||
*/ | ||
private static $sites_list; | ||
|
||
/** | ||
* Hold an instance of WP_MS_Sites_List_Table | ||
* | ||
* @var WP_MS_Sites_List_Table | ||
*/ | ||
public $table = false; | ||
|
||
/** | ||
* Skip all tests for non-multisite runs. | ||
* Set up an instance variable to hold a `WP_MS_Sites_List_Table` object. | ||
* | ||
* @return void | ||
*/ | ||
public function set_up(): void { | ||
parent::set_up(); | ||
|
||
if ( ! is_multisite() ) { | ||
self::markTestSkipped(); | ||
} | ||
|
||
$this->table = _get_list_table( 'WP_MS_Sites_List_Table', array( 'screen' => 'ms-sites' ) ); | ||
self::$sites_list = new Network_Admin_Sites_List( new Parsely() ); | ||
} | ||
|
||
/** | ||
* Make sure the custom column is included. | ||
* | ||
* @covers \Parsely\UI\Network_Admin_Sites_List::add_api_key_column | ||
* @covers \Parsely\UI\Network_Admin_Sites_List::run | ||
* @uses \Parsely\UI\Network_Admin_Sites_List::__construct | ||
* @return void | ||
*/ | ||
public function test_api_key_column_is_present(): void { | ||
$columns = $this->table->get_columns(); | ||
self::assertArrayNotHasKey( 'parsely-api-key', $columns ); | ||
|
||
self::$sites_list->run(); | ||
$columns = $this->table->get_columns(); | ||
|
||
self::assertArrayHasKey( 'parsely-api-key', $columns ); | ||
self::assertSame( 'Parse.ly API Key', $columns['parsely-api-key'] ); | ||
} | ||
|
||
/** | ||
* Make sure the custom column is populated with default data for no option and the API key when set. | ||
* | ||
* @covers \Parsely\UI\Network_Admin_Sites_List::populate_api_key_column | ||
* @covers \Parsely\UI\Network_Admin_Sites_List::run | ||
* @uses \Parsely\Parsely::api_key_is_set | ||
* @uses \Parsely\Parsely::get_api_key | ||
* @uses \Parsely\Parsely::get_options | ||
* @uses \Parsely\UI\Network_Admin_Sites_List::__construct | ||
* @return void | ||
*/ | ||
public function test_api_key_column_is_correctly_printed(): void { | ||
$blog_id_with_api_key = $this->factory->blog->create(); | ||
$blog_id_without_api_key = $this->factory->blog->create(); | ||
|
||
self::$sites_list->run(); | ||
|
||
update_blog_option( $blog_id_with_api_key, Parsely::OPTIONS_KEY, array( 'apikey' => 'parselyrocks.example.com' ) ); | ||
|
||
$this->table->prepare_items(); | ||
|
||
self::assertCount( 3, $this->table->items, 'There should be the main site, the subsite with the apikey set, and a subsite without.' ); | ||
|
||
foreach ( $this->table->items as $site ) { | ||
self::assertInstanceOf( WP_Site::class, $site ); | ||
|
||
ob_start(); | ||
$this->table->column_default( $site->to_array(), 'parsely-api-key' ); | ||
$api_key_col_value = ob_get_clean(); | ||
|
||
if ( $blog_id_with_api_key === (int) $site->blog_id ) { | ||
self::assertSame( | ||
'parselyrocks.example.com', | ||
$api_key_col_value, | ||
'The API key was not printed and should have been.' | ||
); | ||
} else { | ||
self::assertSame( | ||
'<em>Parse.ly API key is missing</em>', | ||
$api_key_col_value, | ||
'The default value was not printed and should have been.' | ||
); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters