Skip to content

Commit 40a60ac

Browse files
committed
Add warning for when the LLMs.txt cannot be generated in our dashboard.
1 parent d588300 commit 40a60ac

File tree

6 files changed

+372
-0
lines changed

6 files changed

+372
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong
4+
namespace Yoast\WP\SEO\Llms_Txt\Application\File;
5+
6+
use WPSEO_Shortlinker;
7+
use Yoast\WP\SEO\Presenters\Abstract_Presenter;
8+
9+
/**
10+
* Class File_Failure_Notification_Presenter.
11+
*/
12+
class File_Failure_Notification_Presenter extends Abstract_Presenter {
13+
14+
/**
15+
* Returns the notification as an HTML string.
16+
*
17+
* @return string The notification in an HTML string representation.
18+
*/
19+
public function present() {
20+
$notification_text = '<p>';
21+
$notification_text .= $this->get_message();
22+
$notification_text .= '</p>';
23+
24+
return $notification_text;
25+
}
26+
27+
/**
28+
* Returns the message to show.
29+
*
30+
* @return string The message.
31+
*/
32+
protected function get_message() {
33+
return \sprintf(
34+
'<strong>%1$s</strong> %2$s',
35+
\esc_html__( 'Your llms.txt file couldn\'t be auto-generated', 'wordpress-seo' ),
36+
\sprintf(
37+
/* translators: 1: Link start tag to the WordPress Reading Settings page, 2: Link closing tag. */
38+
\esc_html__( 'It looks like there is an llms.txt file already that wasn\'t created by Yoast, or the llms.txt file created by Yoast has been edited manually. We don\'t want to overwrite this file\'s content, so if you want to let Yoast keep auto-generating the llms.txt file, you can %1$smanually delete the existing one%2$s. Otherwise, consider disabling the Yoast feature.', 'wordpress-seo' ),
39+
'<a href="' . \esc_url( WPSEO_Shortlinker::get( 'https://yoa.st/llms-txt-file-deletion' ) ) . '">',
40+
'</a>'
41+
)
42+
);
43+
}
44+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
namespace Yoast\WP\SEO\Llms_Txt\User_Interface;
4+
5+
use Yoast\WP\SEO\Conditionals\No_Conditionals;
6+
use Yoast\WP\SEO\Helpers\Options_Helper;
7+
use Yoast\WP\SEO\Integrations\Integration_Interface;
8+
use Yoast\WP\SEO\Llms_Txt\Application\File\Commands\Populate_File_Command_Handler;
9+
use Yoast\WP\SEO\Llms_Txt\Application\File\File_Failure_Notification_Presenter;
10+
use Yoast_Notification;
11+
use Yoast_Notification_Center;
12+
13+
/**
14+
* Watches and handles changes to the LLMS.txt file failure option.
15+
*/
16+
class File_Failure_Llms_Txt_Notification_Integration implements Integration_Interface {
17+
use No_Conditionals;
18+
19+
/**
20+
* The notification ID.
21+
*/
22+
public const NOTIFICATION_ID = 'wpseo-llms-txt-generation-failure';
23+
24+
/**
25+
* The options helper.
26+
*
27+
* @var Options_Helper
28+
*/
29+
private $options_helper;
30+
31+
/**
32+
* The notification center.
33+
*
34+
* @var Yoast_Notification_Center
35+
*/
36+
private $notification_center;
37+
38+
/**
39+
* The notification presenter.
40+
*
41+
* @var File_Failure_Notification_Presenter
42+
*/
43+
private $presenter;
44+
45+
/**
46+
* Constructor.
47+
*
48+
* @param Options_Helper $options_helper The options helper.
49+
* @param Yoast_Notification_Center $notification_center The notification center.
50+
* @param File_Failure_Notification_Presenter $presenter The notification presenter.
51+
*/
52+
public function __construct(
53+
Options_Helper $options_helper,
54+
Yoast_Notification_Center $notification_center,
55+
File_Failure_Notification_Presenter $presenter
56+
) {
57+
$this->options_helper = $options_helper;
58+
$this->notification_center = $notification_center;
59+
$this->presenter = $presenter;
60+
}
61+
62+
/**
63+
* Initializes the integration.
64+
*
65+
* This is the place to register hooks and filters.
66+
*
67+
* @return void
68+
*/
69+
public function register_hooks() {
70+
\add_action( 'admin_init', [ $this, 'maybe_show_notification' ], 10, 2 );
71+
}
72+
73+
/**
74+
* Manage the search engines discouraged notification.
75+
*
76+
* Shows the notification if needed and deletes it if needed.
77+
*
78+
* @return void
79+
*/
80+
public function maybe_show_notification() {
81+
if ( ! $this->should_show_file_failure_notification() ) {
82+
$this->remove_file_failure_notification_if_exists();
83+
}
84+
else {
85+
$this->maybe_add_file_failure_notification();
86+
}
87+
}
88+
89+
/**
90+
* Whether the file failure notification should be shown.
91+
*
92+
* @return bool
93+
*/
94+
private function should_show_file_failure_notification(): bool {
95+
return \get_option( Populate_File_Command_Handler::GENERATION_FAILURE_OPTION, false ) !== false;
96+
}
97+
98+
/**
99+
* Remove the search engines discouraged notification if it exists.
100+
*
101+
* @return void
102+
*/
103+
private function remove_file_failure_notification_if_exists() {
104+
$this->notification_center->remove_notification_by_id( self::NOTIFICATION_ID );
105+
}
106+
107+
/**
108+
* Add the search engines discouraged notification if it does not exist yet.
109+
*
110+
* @return void
111+
*/
112+
private function maybe_add_file_failure_notification() {
113+
if ( ! $this->notification_center->get_notification_by_id( self::NOTIFICATION_ID ) ) {
114+
$notification = new Yoast_Notification(
115+
$this->presenter->present(),
116+
[
117+
'type' => Yoast_Notification::ERROR,
118+
'id' => self::NOTIFICATION_ID,
119+
'capabilities' => 'wpseo_manage_options',
120+
'priority' => 1,
121+
]
122+
);
123+
$this->notification_center->restore_notification( $notification );
124+
$this->notification_center->add_notification( $notification );
125+
}
126+
}
127+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3+
// phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded
4+
namespace Yoast\WP\SEO\Tests\Unit\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration;
5+
6+
use Mockery;
7+
use Yoast\WP\SEO\Helpers\Options_Helper;
8+
use Yoast\WP\SEO\Llms_Txt\Application\File\File_Failure_Notification_Presenter;
9+
use Yoast\WP\SEO\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration;
10+
use Yoast\WP\SEO\Tests\Unit\TestCase;
11+
use Yoast_Notification_Center;
12+
13+
/**
14+
* Abstract class for the Content_Types_Collector tests.
15+
*
16+
* @group llms.txt
17+
*/
18+
abstract class Abstract_File_Failure_Llms_Txt_Notification_Integration_Test extends TestCase {
19+
20+
/**
21+
* Holds the instance.
22+
*
23+
* @var File_Failure_Llms_Txt_Notification_Integration
24+
*/
25+
protected $instance;
26+
27+
/**
28+
* The notification center mock.
29+
*
30+
* @var Mockery\MockInterface|Yoast_Notification_Center
31+
*/
32+
protected $notification_center;
33+
34+
/**
35+
* The options helper mock.
36+
*
37+
* @var Mockery\MockInterface|Options_Helper
38+
*/
39+
protected $options_helper;
40+
41+
/**
42+
* The file failure notification presenter mock.
43+
*
44+
* @var Mockery\MockInterface|File_Failure_Notification_Presenter
45+
*/
46+
protected $file_failure_notification_presenter;
47+
48+
/**
49+
* Sets up the test fixtures.
50+
*
51+
* @return void
52+
*/
53+
protected function set_up() {
54+
parent::set_up();
55+
56+
$this->notification_center = Mockery::mock( Yoast_Notification_Center::class );
57+
$this->options_helper = Mockery::mock( Options_Helper::class );
58+
$this->file_failure_notification_presenter = Mockery::mock( File_Failure_Notification_Presenter::class );
59+
60+
$this->instance = new File_Failure_Llms_Txt_Notification_Integration(
61+
$this->options_helper,
62+
$this->notification_center,
63+
$this->file_failure_notification_presenter
64+
);
65+
}
66+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3+
// phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded
4+
namespace Yoast\WP\SEO\Tests\Unit\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration;
5+
6+
use Yoast\WP\SEO\Helpers\Options_Helper;
7+
use Yoast\WP\SEO\Llms_Txt\Application\File\File_Failure_Notification_Presenter;
8+
use Yoast_Notification_Center;
9+
10+
/**
11+
* Tests the File_Failure_Llms_Txt_Notification_Integration constructor.
12+
*
13+
* @group llms.txt
14+
*
15+
* @covers Yoast\WP\SEO\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration::__construct
16+
*/
17+
final class Constructor_Test extends Abstract_File_Failure_Llms_Txt_Notification_Integration_Test {
18+
19+
/**
20+
* Tests the constructor.
21+
*
22+
* @return void
23+
*/
24+
public function test_constructor() {
25+
$this->assertInstanceOf(
26+
Options_Helper::class,
27+
$this->getPropertyValue( $this->instance, 'options_helper' )
28+
);
29+
$this->assertInstanceOf(
30+
Yoast_Notification_Center::class,
31+
$this->getPropertyValue( $this->instance, 'notification_center' )
32+
);
33+
$this->assertInstanceOf(
34+
File_Failure_Notification_Presenter::class,
35+
$this->getPropertyValue( $this->instance, 'presenter' )
36+
);
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3+
// phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded
4+
namespace Yoast\WP\SEO\Tests\Unit\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration;
5+
6+
use Brain\Monkey;
7+
8+
/**
9+
* Tests the File_Failure_Llms_Txt_Notification_Integration maybe_show_notification.
10+
*
11+
* @group llms.txt
12+
*
13+
* @covers Yoast\WP\SEO\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration::maybe_show_notification
14+
*/
15+
final class Maybe_Show_Notification_Test extends Abstract_File_Failure_Llms_Txt_Notification_Integration_Test {
16+
17+
/**
18+
* Tests the maybe_show_notification when there is a failure.
19+
*
20+
* @return void
21+
*/
22+
public function test_maybe_show_notification_option_set_no_notification() {
23+
Monkey\Functions\expect( 'get_option' )
24+
->once()
25+
->with( 'wpseo_llms_txt_file_failure', false )
26+
->andReturn( 'failure' );
27+
Monkey\Functions\expect( 'get_current_user_id' )->andReturn( 1 );
28+
$this->notification_center->expects( 'get_notification_by_id' )->andReturnFalse();
29+
$this->notification_center->expects( 'restore_notification' );
30+
$this->notification_center->expects( 'add_notification' );
31+
$this->file_failure_notification_presenter->expects( 'present' );
32+
$this->instance->maybe_show_notification();
33+
}
34+
35+
/**
36+
* Tests the maybe_show_notification when there is a failure but the notification already exists.
37+
*
38+
* @return void
39+
*/
40+
public function test_maybe_show_notification_option_set_notification_exists() {
41+
Monkey\Functions\expect( 'get_option' )
42+
->once()
43+
->with( 'wpseo_llms_txt_file_failure', false )
44+
->andReturn( 'failure' );
45+
Monkey\Functions\expect( 'get_current_user_id' )->andReturn( 1 );
46+
$this->notification_center->expects( 'get_notification_by_id' )->andReturnTrue();
47+
$this->notification_center->expects( 'restore_notification' )->never();
48+
$this->notification_center->expects( 'add_notification' )->never();
49+
50+
$this->instance->maybe_show_notification();
51+
}
52+
53+
/**
54+
* Tests the maybe_show_notification without failure.
55+
*
56+
* @return void
57+
*/
58+
public function test_maybe_show_notification_option_not_set() {
59+
$this->notification_center->expects( 'remove_notification_by_id' )->with( 'wpseo-llms-txt-generation-failure' );
60+
Monkey\Functions\expect( 'get_option' )
61+
->once()
62+
->with( 'wpseo_llms_txt_file_failure', false )
63+
->andReturn( false );
64+
$this->instance->maybe_show_notification();
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3+
// phpcs:disable Yoast.NamingConventions.NamespaceName.MaxExceeded
4+
namespace Yoast\WP\SEO\Tests\Unit\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration;
5+
6+
/**
7+
* Tests the File_Failure_Llms_Txt_Notification_Integration register_hooks.
8+
*
9+
* @group llms.txt
10+
*
11+
* @covers Yoast\WP\SEO\Llms_Txt\User_Interface\File_Failure_Llms_Txt_Notification_Integration::register_hooks
12+
*/
13+
final class Register_Hooks_Test extends Abstract_File_Failure_Llms_Txt_Notification_Integration_Test {
14+
15+
/**
16+
* Tests the registration of the hooks.
17+
*
18+
* @return void
19+
*/
20+
public function test_register_hooks() {
21+
$this->instance->register_hooks();
22+
23+
$this->assertEquals(
24+
10,
25+
\has_action(
26+
'admin_init',
27+
[ $this->instance, 'maybe_show_notification' ]
28+
)
29+
);
30+
}
31+
}

0 commit comments

Comments
 (0)