Skip to content

Commit

Permalink
Merge pull request #39 from Yoast/stories/38-make-message-dismissible
Browse files Browse the repository at this point in the history
Makes message dismissible
  • Loading branch information
moorscode authored Jul 31, 2017
2 parents e209514 + 67fcef0 commit 0f38cde
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 6 deletions.
54 changes: 54 additions & 0 deletions src/Whip_MessageDismisser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php


/**
* A class to dismiss messages.
*/
class Whip_MessageDismisser {

/** @var Whip_DismissStorage */
protected $storage;

/** @var string */
protected $currentVersion;

/**
* Whip_MessageDismisser constructor.
*
* @param string $currentVersion The current version of the installation.
* @param Whip_DismissStorage $storage The storage object handling storage of versioning.
*/
public function __construct( $currentVersion, Whip_DismissStorage $storage ) {
$this->currentVersion = $this->toMajorVersion( $currentVersion );
$this->storage = $storage;
}

/**
* Saves the version number to the storage to indicate the message as being dismissed.
*/
public function dismiss() {
$this->storage->set( $this->currentVersion );
}

/**
* Checks if the stored version is equal or higher than the version to check against.
*
* @return bool True when saved version is equal or higher than the provided version.
*/
public function isDismissed() {
return version_compare( $this->storage->get(), $this->currentVersion, '>=' );
}

/**
* Converts the version number to a major version number.
*
* @param string $versionToConvert The version to convert.
*
* @return string The major version number.
*/
protected function toMajorVersion( $versionToConvert ) {
$parts = explode( '.', $versionToConvert, 3 );

return implode( '.', array_slice( $parts, 0, 2 ) );
}
}
2 changes: 1 addition & 1 deletion src/Whip_RequirementsChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Whip_RequirementsChecker {
* @param array $configuration The configuration to check.
* @param string $textdomain The text domain to use for translations.
*/
public function __construct( $configuration = array(), $textdomain = 'wordpress-seo' ) {
public function __construct( $configuration = array(), $textdomain = 'wordpress' ) {
$this->requirements = array();
$this->configuration = new Whip_Configuration( $configuration );
$this->messageMananger = new Whip_MessagesManager();
Expand Down
36 changes: 36 additions & 0 deletions src/Whip_WPDismissOption.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/**
* Represents the WordPress option for saving the dismissed messages.
*/
class Whip_WPDismissOption implements Whip_DismissStorage {

/** @var string */
protected $optionName = 'whip_dismissed_for_wp_version';

/**
* Saves the value to the options.
*
* @param string $dismissedVersion The value to save.
*
* @return bool True when successful.
*/
public function set( $dismissedVersion ) {
return update_option( $this->optionName, $dismissedVersion );
}

/**
* Returns the value of the whip_dismissed option.
*
* @return string Returns the value of the option or an empty string when not set.
*/
public function get() {
$dismissedOption = get_option( $this->optionName );
if ( ! $dismissedOption ) {
return '';
}

return $dismissedOption;
}

}
51 changes: 51 additions & 0 deletions src/Whip_WPMessageDismissListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/**
* Listener for dismissing a message.
*/
class Whip_WPMessageDismissListener implements Whip_Listener {

const ACTION_NAME = 'whip_dismiss';

/**
* @var Whip_MessageDismisser
*/
protected $dismisser;

/**
* Sets the dismisser attribute.
*
* @param Whip_MessageDismisser $dismisser The object for dismissing a message.
*/
public function __construct( Whip_MessageDismisser $dismisser ) {
$this->dismisser = $dismisser;
}

/**
* Listens to a GET request to fetch the required attributes.
*
* @return void
*/
public function listen() {
$action = filter_input( INPUT_GET, 'action' );
$nonce = filter_input( INPUT_GET, 'nonce' );

if ( $action === self::ACTION_NAME && wp_verify_nonce( $nonce, self::ACTION_NAME ) ) {
$this->dismisser->dismiss();
}
}

/**
* Creates an url for dismissing the notice.
*
* @return string The url for dismissing the message.
*/
public function getDismissURL() {
return sprintf(
admin_url( 'index.php?action=%1$s&nonce=%2$s' ),
self::ACTION_NAME,
wp_create_nonce( self::ACTION_NAME )
);
}

}
6 changes: 5 additions & 1 deletion src/facades/wordpress.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ function whip_wp_check_versions( $requirements ) {
return;
}

global $wp_version;

$config = include dirname( __FILE__ ) . '/../configs/default.php';
$checker = new Whip_RequirementsChecker( $config );

Expand All @@ -25,7 +27,9 @@ function whip_wp_check_versions( $requirements ) {
return;
}

$presenter = new Whip_WPMessagePresenter( $checker->getMostRecentMessage() );
$dismisser = new Whip_MessageDismisser( $wp_version, new Whip_WPDismissOption() );

$presenter = new Whip_WPMessagePresenter( $checker->getMostRecentMessage(), $dismisser );
$presenter->register_hooks();
}
}
24 changes: 24 additions & 0 deletions src/interfaces/Whip_DismissStorage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* Interface Whip_DismissStorage.
*/
interface Whip_DismissStorage {

/**
* Saves the value.
*
* @param string $dismissedVersion The value to save.
*
* @return bool True when successful.
*/
public function set( $dismissedVersion );

/**
* Returns the value.
*
* @return string
*/
public function get();

}
15 changes: 15 additions & 0 deletions src/interfaces/Whip_Listener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

/**
* Interface Whip_Listener.
*/
interface Whip_Listener {

/**
* Method that should implement the listen functionality.
*
* @return void
*/
public function listen();

}
29 changes: 25 additions & 4 deletions src/presenters/Whip_WPMessagePresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,28 @@ class Whip_WPMessagePresenter implements Whip_MessagePresenter {

private $message;

/** @var Whip_MessageDismisser */
private $dismisser;

/**
* Whip_WPMessagePresenter constructor.
*
* @param Whip_Message $message The message to use in the presenter.
* @param Whip_Message $message The message to use in the presenter.
* @param Whip_MessageDismisser $dismisser Dismisser object.
*/
public function __construct( Whip_Message $message ) {
$this->message = $message;
public function __construct( Whip_Message $message, Whip_MessageDismisser $dismisser ) {
$this->message = $message;
$this->dismisser = $dismisser;
}

/**
* Registers hooks to WordPress. This is a separate function so you can
* control when the hooks are registered.
*
*/
public function register_hooks() {
global $whip_admin_notices_added;

if ( null === $whip_admin_notices_added || ! $whip_admin_notices_added ) {
add_action( 'admin_notices', array( $this, 'renderMessage' ) );
$whip_admin_notices_added = true;
Expand All @@ -32,7 +39,21 @@ public function register_hooks() {
* Renders the messages present in the global to notices.
*/
public function renderMessage() {
printf( '<div class="error">%s</div>', $this->kses( $this->message->body() ) );
$dismissListener = new Whip_WPMessageDismissListener( $this->dismisser );
$dismissListener->listen();

if ( $this->dismisser->isDismissed() ) {
return;
}

/* translators: 1: is a link to dismiss url 2: closing link tag */
$dismissButton = sprintf(
__( '<p>%1$sRemind me again after the next WordPress release.%2$s</p>', 'wordpress' ),
'<a href="' . $dismissListener->getDismissURL() . '">',
'</a>'
);

printf( '<div class="error">%1$s<p>%2$s</p></div>', $this->kses( $this->message->body() ), $dismissButton );
}

/**
Expand Down
72 changes: 72 additions & 0 deletions tests/MessageDismisserTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

class Whip_DismissStorageMock implements Whip_DismissStorage {

/** @var string */
protected $dismissed = '';

/**
* Saves the value.
*
* @param string $dismissedVersion The value to save.
*/
public function set( $dismissedVersion ) {
$this->dismissed = $dismissedVersion;
}

/**
* Returns the value.
*
* @return string
*/
public function get() {
return $this->dismissed;
}
}

class MessageDismisserTest extends PHPUnit_Framework_TestCase {

/**
* @covers Whip_MessageDismisser::__construct()
* @covers Whip_MessageDismisser::dismiss()
*/
public function testDismiss() {
$storage = new Whip_DismissStorageMock();
$dismisser = new Whip_MessageDismisser( '4.8', $storage );

$dismisser->dismiss();

$this->assertEquals( '4.8' , $storage->get() );
}

/**
* @dataProvider versionNumbersProvider
*
* @param string $savedVersion The saved version number.
* @param string $currentVersion The current version number.
* @param bool $expected The expected value.
*
* @covers Whip_MessageDismisser::__construct()
* @covers Whip_MessageDismisser::isDismissed()
* @covers Whip_MessageDismisser::toMajorVersion()
*/
public function testIsDismissibleWithVersions( $savedVersion, $currentVersion, $expected ) {
$storage = new Whip_DismissStorageMock();
$storage->set( $savedVersion );
$dismisser = new Whip_MessageDismisser( $currentVersion, $storage );

$this->assertEquals( $expected, $dismisser->isDismissed() );
}

public function versionNumbersProvider() {
return array(
array( '4.8', '4.8', true ),
array( '4.8', '4.8.1', true ),
array( '4.7', '4.8', false ),
array( '4.7', '4.8.1', false ),
array( '4.7.1', '4.8.1', false ),
array( '4.7', '4.7-alpha', true ),
);
}

}

0 comments on commit 0f38cde

Please sign in to comment.