From 0dadfb9ed1949a36071479d881800edcabfbc9ea Mon Sep 17 00:00:00 2001 From: Sebastian Thulin Date: Fri, 29 Nov 2024 15:37:58 +0100 Subject: [PATCH 1/7] fix: link updater --- source/php/LinkUpdater/LinkUpdater.php | 39 ++++++++----------- .../php/LinkUpdater/LinkUpdaterInterface.php | 4 +- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/source/php/LinkUpdater/LinkUpdater.php b/source/php/LinkUpdater/LinkUpdater.php index 9ffe10f..6a133cb 100644 --- a/source/php/LinkUpdater/LinkUpdater.php +++ b/source/php/LinkUpdater/LinkUpdater.php @@ -7,6 +7,7 @@ use BrokenLinkDetector\Config\Config; use BrokenLinkDetector\Database\Database; use BrokenLinkDetector\HooksRegistrar\Hookable; +use WP_Post; class LinkUpdater implements LinkUpdaterInterface, Hookable { @@ -20,7 +21,7 @@ public function __construct(private WpService $wpService, private Config $config */ public function addHooks(): void { - $this->wpService->addFilter('wp_insert_post_data', array($this, 'updateLinks'), 10, 2); + $this->wpService->addAction('wp_after_insert_post', array($this, 'updateLinks'), 10, 3); } /** @@ -29,30 +30,22 @@ public function addHooks(): void * @param array $post * @return bool */ - public function updateLinks(array $data, array $post): array + public function updateLinks(int|WP_Post $post, bool $isUpdate, null|WP_Post $postBefore): void { - if(is_null($post)) { - return $data; + if(!$isUpdate) { + return; } - foreach(['post_type', 'post_name'] as $keys) { - if(!isset($data[$keys]) || !isset($post[$keys])) { - return $data; - } + if(!is_a($post, 'WP_Post') && is_numeric($post)) { + $post = $this->wpService->getPost($post); } - if($this->linkHasChanged($data, $post) && $this->shouldReplaceForPosttype($data['post_type'])) { - - $postId = $post['ID'] ?? null; - - if(is_numeric($postId)) { - $this->replaceLinks( - $this->createPermalink($postId, $data['post_name']), - $this->createPermalink($postId, $post['post_name']) - ); - } + if($this->linkHasChanged($post, $postBefore) && $this->shouldReplaceForPosttype($this->wpService->getPostType($post))) { + $this->replaceLinks( + $this->createPermalink($post->ID, $postBefore->post_name), + $this->createPermalink($post->ID, $post->post_name) + ); } - return $data; } /** @@ -100,13 +93,13 @@ public function createPermalink(int $postId, string $postName): string /** * Check if the link has changed - * @param array $data The newly submitted data - * @param array $post The stored post data + * @param WP_Post $post The newly submitted data + * @param WP_Post $postBefore The stored post data * @return bool */ - public function linkHasChanged(array $data, array $post): bool + public function linkHasChanged(WP_Post $post, WP_Post $postBefore): bool { - return $data['post_name'] !== $post['post_name']; + return $post->post_name !== $postBefore->post_name; } /** diff --git a/source/php/LinkUpdater/LinkUpdaterInterface.php b/source/php/LinkUpdater/LinkUpdaterInterface.php index 62b8739..6fe7e91 100644 --- a/source/php/LinkUpdater/LinkUpdaterInterface.php +++ b/source/php/LinkUpdater/LinkUpdaterInterface.php @@ -1,8 +1,8 @@ Date: Fri, 29 Nov 2024 16:06:39 +0100 Subject: [PATCH 2/7] fix: enable feature --- source/php/Config/Feature.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/php/Config/Feature.php b/source/php/Config/Feature.php index ab649e0..aba58c1 100644 --- a/source/php/Config/Feature.php +++ b/source/php/Config/Feature.php @@ -18,7 +18,7 @@ class Feature implements FeatureInterface { 'admin_highlight_links' => 1, //On save autofixer - 'fix_internal_links' => false, + 'fix_internal_links' => 1, 'maintain_link_registry' => 1, //CLI Features From 2fbab91fd5b32a1bdf2fabd7e4c77fde295415dc Mon Sep 17 00:00:00 2001 From: Sebastian Thulin Date: Mon, 2 Dec 2024 13:04:16 +0100 Subject: [PATCH 3/7] fix: get real links --- source/php/LinkUpdater/LinkUpdater.php | 170 ++++++++---------- .../php/LinkUpdater/LinkUpdaterInterface.php | 2 +- 2 files changed, 78 insertions(+), 94 deletions(-) diff --git a/source/php/LinkUpdater/LinkUpdater.php b/source/php/LinkUpdater/LinkUpdater.php index 6a133cb..b2e0b85 100644 --- a/source/php/LinkUpdater/LinkUpdater.php +++ b/source/php/LinkUpdater/LinkUpdater.php @@ -1,5 +1,4 @@ -wpService->addAction('wp_after_insert_post', array($this, 'updateLinks'), 10, 3); + private ?string $storedPermalink = null; + + public function __construct(private WpService $wpService, private Config $config, private Database $database) + { + } + + /** + * Add hooks for the link updater + * @return void + */ + public function addHooks(): void + { + //Fetches the previous permalink before the post is updated + $this->wpService->addFilter('pre_post_update', [$this, 'beforeUpdateLinks'], 10, 2); + + //Updates the links in the post content if the post name has changed + $this->wpService->addAction('post_updated', [$this, 'updateLinks'], 10, 3); + } + + /** + * Before the post is updated, store the post data + * @param int $postId + * @param array $post + * @return void + */ + public function beforeUpdateLinks(int $postId, array $post): void + { + $this->storedPermalink = $this->wpService->getPermalink($postId); + } + + /** + * Update the links in the post content if the post name has changed + * @param int $id + * @param WP_Post $postBefore + * @param WP_Post $postAfter + * @return void + */ + public function updateLinks(int $postId, WP_Post $postBefore, WP_Post $postAfter): void + { + if ($this->storedPermalink === null) { + return; } - /** - * Update the links in the post content if the post name has changed - * @param array $data - * @param array $post - * @return bool - */ - public function updateLinks(int|WP_Post $post, bool $isUpdate, null|WP_Post $postBefore): void - { - if(!$isUpdate) { - return; - } - - if(!is_a($post, 'WP_Post') && is_numeric($post)) { - $post = $this->wpService->getPost($post); - } + $previousPermalink = $this->storedPermalink; + $currentPermalink = $this->wpService->getPermalink($postId); - if($this->linkHasChanged($post, $postBefore) && $this->shouldReplaceForPosttype($this->wpService->getPostType($post))) { - $this->replaceLinks( - $this->createPermalink($post->ID, $postBefore->post_name), - $this->createPermalink($post->ID, $post->post_name) - ); + if ($previousPermalink != $currentPermalink && $this->shouldReplaceForPosttype($postAfter->post_type)) { + //Ensure that the home url is not replaced + if($this->wpService->homeUrl() !== $previousPermalink) { + $this->replaceLinks($previousPermalink, $currentPermalink); } } - - /** - * Replace the old link with the new link in posts that contains the link - * @param string $newLink - * @param string $oldLink - * @return int - */ - private function replaceLinks(string $newLink, string $oldLink): int - { - + } + + /** + * Replace the old link with the new link in the post content + * @param string $oldLink + * @param string $newLink + * @return int + */ + private function replaceLinks(string $oldLink, string $newLink): int + { $db = $this->database->getInstance(); - $db->query( - $db->prepare( - "UPDATE $db->posts - SET post_content = REPLACE(post_content, %s, %s) - WHERE post_content LIKE %s", - $oldLink, - $newLink, - '%' . $db->esc_like($oldLink) . '%' - ) + $db->prepare( + "UPDATE $db->posts + SET post_content = REPLACE(post_content, %s, %s) + WHERE post_content LIKE %s", + $oldLink, + $newLink, + '%' . $db->esc_like($oldLink) . '%' + ) ); - return $db->rows_affected; - } - - /** - * Create a permalink from the post id and post name - * @param int $postId - * @param string $postName - * @return string - */ - public function createPermalink(int $postId, string $postName): string - { - $permalink = preg_replace('/[^\/]+\/?$/', - $postName, - $this->wpService->getPermalink($postId) - ); - - $permalink = rtrim($permalink, '/'); - - return $permalink; - } - - /** - * Check if the link has changed - * @param WP_Post $post The newly submitted data - * @param WP_Post $postBefore The stored post data - * @return bool - */ - public function linkHasChanged(WP_Post $post, WP_Post $postBefore): bool - { - return $post->post_name !== $postBefore->post_name; - } - - /** - * Check if the link should be replaced for the post type - * @param string $postType - * @return bool - */ - private function shouldReplaceForPosttype(string $postType): bool - { - return !in_array($postType, $this->config->linkUpdaterBannedPostTypes()); - } + } + + /** + * Check if the post type should be replaced + * @param string $postType + * @return bool + */ + private function shouldReplaceForPosttype(string $postType): bool + { + return !in_array($postType, $this->config->linkUpdaterBannedPostTypes()); + } } \ No newline at end of file diff --git a/source/php/LinkUpdater/LinkUpdaterInterface.php b/source/php/LinkUpdater/LinkUpdaterInterface.php index 6fe7e91..f632e16 100644 --- a/source/php/LinkUpdater/LinkUpdaterInterface.php +++ b/source/php/LinkUpdater/LinkUpdaterInterface.php @@ -4,5 +4,5 @@ use WP_Post; interface LinkUpdaterInterface { - public function updateLinks(int|WP_Post $post, bool $isUpdate, null|WP_Post $postBefore): void; + public function updateLinks(int $postId, WP_Post $postBefore, WP_Post $postAfter): void; } \ No newline at end of file From eddc340be4962de09361b808d34ce4980c6a4b33 Mon Sep 17 00:00:00 2001 From: Sebastian Thulin Date: Mon, 2 Dec 2024 13:15:30 +0100 Subject: [PATCH 4/7] fix: add valid function --- source/php/LinkUpdater/LinkUpdater.php | 44 +++++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/source/php/LinkUpdater/LinkUpdater.php b/source/php/LinkUpdater/LinkUpdater.php index b2e0b85..3f96ec8 100644 --- a/source/php/LinkUpdater/LinkUpdater.php +++ b/source/php/LinkUpdater/LinkUpdater.php @@ -49,19 +49,47 @@ public function beforeUpdateLinks(int $postId, array $post): void */ public function updateLinks(int $postId, WP_Post $postBefore, WP_Post $postAfter): void { - if ($this->storedPermalink === null) { + $previousPermalink = $this->storedPermalink; + $currentPermalink = $this->wpService->getPermalink($postId); + + if (!$this->isValidReplaceRequest($previousPermalink, $currentPermalink)) { return; } - $previousPermalink = $this->storedPermalink; - $currentPermalink = $this->wpService->getPermalink($postId); + if ($this->shouldReplaceForPosttype($postAfter->post_type)) { + $this->replaceLinks($previousPermalink, $currentPermalink); + } + } + + /** + * Validate the replace request + * @param string $oldLink + * @param string $newLink + * @return bool + */ + private function isValidReplaceRequest(string $oldLink, string $newLink): bool + { + //Ensure that the old link is not the same as the new link + if ($oldLink === $newLink) { + return false; + } - if ($previousPermalink != $currentPermalink && $this->shouldReplaceForPosttype($postAfter->post_type)) { - //Ensure that the home url is not replaced - if($this->wpService->homeUrl() !== $previousPermalink) { - $this->replaceLinks($previousPermalink, $currentPermalink); - } + //Ensure that the old link is not empty + if (empty($oldLink)) { + return false; } + + //Ensure that the new link is not empty + if (empty($newLink)) { + return false; + } + + //Ensure that the old link is not a home url + if ($this->wpService->homeUrl() === $oldLink) { + return false; + } + + return true; } /** From 65aa2ec826add8fdc4eaa43c51b0c4b7cc6854cc Mon Sep 17 00:00:00 2001 From: Sebastian Thulin Date: Mon, 2 Dec 2024 13:19:42 +0100 Subject: [PATCH 5/7] Delete LinkUpdater.test.php --- source/php/LinkUpdater/LinkUpdater.test.php | 114 -------------------- 1 file changed, 114 deletions(-) delete mode 100644 source/php/LinkUpdater/LinkUpdater.test.php diff --git a/source/php/LinkUpdater/LinkUpdater.test.php b/source/php/LinkUpdater/LinkUpdater.test.php deleted file mode 100644 index 13ba14c..0000000 --- a/source/php/LinkUpdater/LinkUpdater.test.php +++ /dev/null @@ -1,114 +0,0 @@ - $input, - 'getOption' => 'option' - ]); - $acfService = new FakeAcfService([]); - - $config = new Config( - $wpService, - $acfService, - 'filter-prefix', - 'plugin-path', - 'plugin-url' - ); - - $postId = 123; - - $linkUpdater = new LinkUpdater( - $wpService, - $config, - new Database( - $config, - $wpService - ) - ); - - // Act - $result = $linkUpdater->createPermalink($postId, $postName); - - // Assert - $this->assertEquals($expected, $result); - } - - /** - * Test urls. - */ - public function testThatLinkHasChangedDetectsLinksThatChanges() - { - // Arrange - $wpService = new FakeWpService([ - 'getPermalink' => 'https://example.com/old-permalink/', - 'getOption' => 'option', - 'applyFilters' => function($filter, $value) { - return $value; - } - ]); - - $acfService = new FakeAcfService([]); - - $config = new Config( - $wpService, - $acfService, - 'filter-prefix', - 'plugin-path', - 'plugin-url' - ); - - $linkUpdater = new LinkUpdater( - $wpService, - $config, - new Database( - $config, - $wpService - ) - ); - - $data = [ - 'post_name' => 'sample-post', - 'post_type' => 'post' - ]; - - $post = [ - 'ID' => 123, - 'post_name' => 'old-post', - 'post_type' => 'post' - ]; - - $result = $linkUpdater->linkHasChanged($data, $post); - - // Assert - $this->assertTrue($result); - } - - /** - * Test urls. - */ - private function uriProvider() - { - return [ - ['https://example.com/old-permalink/', 'https://example.com/sample-post', 'sample-post'], - ['https://example.com/old-permalink', 'https://example.com/sample-post', 'sample-post'], - ['https://example.com/old-permalink/with/multiple/subs', 'https://example.com/old-permalink/with/multiple/sample-post', 'sample-post'] - ]; - } -} \ No newline at end of file From 06e4dc3b67c020e61c6458d28f499fb49cffb115 Mon Sep 17 00:00:00 2001 From: Sebastian Thulin Date: Mon, 2 Dec 2024 13:36:41 +0100 Subject: [PATCH 6/7] fix: clear the affected posts cache. --- source/php/LinkUpdater/LinkUpdater.php | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/source/php/LinkUpdater/LinkUpdater.php b/source/php/LinkUpdater/LinkUpdater.php index 3f96ec8..ea27fdc 100644 --- a/source/php/LinkUpdater/LinkUpdater.php +++ b/source/php/LinkUpdater/LinkUpdater.php @@ -101,6 +101,18 @@ private function isValidReplaceRequest(string $oldLink, string $newLink): bool private function replaceLinks(string $oldLink, string $newLink): int { $db = $this->database->getInstance(); + + //Get the post ids that contain the old link + $postIds = $db->get_col( + $db->prepare( + "SELECT ID + FROM $db->posts + WHERE post_content LIKE %s", + '%' . $db->esc_like($oldLink) . '%' + ) + ); + + //Update the post content $db->query( $db->prepare( "UPDATE $db->posts @@ -111,9 +123,26 @@ private function replaceLinks(string $oldLink, string $newLink): int '%' . $db->esc_like($oldLink) . '%' ) ); + + //Clear the object cache for the post ids + $this->clearObjectCache($postIds); + + //Return the number of rows affected return $db->rows_affected; } + /** + * Clear the object cache for the post ids + * + * @param array $postIds + */ + private function clearObjectCache(array $postIds): void + { + foreach ($postIds as $postId) { + $this->wpService->cleanPostCache($postId); + } + } + /** * Check if the post type should be replaced * @param string $postType From a3ddd9a6d51f802c4ced427e87045857a9e730a3 Mon Sep 17 00:00:00 2001 From: Sebastian Thulin Date: Mon, 2 Dec 2024 13:48:17 +0100 Subject: [PATCH 7/7] fix: change to action. --- source/php/LinkUpdater/LinkUpdater.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/php/LinkUpdater/LinkUpdater.php b/source/php/LinkUpdater/LinkUpdater.php index ea27fdc..e5e402b 100644 --- a/source/php/LinkUpdater/LinkUpdater.php +++ b/source/php/LinkUpdater/LinkUpdater.php @@ -23,7 +23,7 @@ public function __construct(private WpService $wpService, private Config $config public function addHooks(): void { //Fetches the previous permalink before the post is updated - $this->wpService->addFilter('pre_post_update', [$this, 'beforeUpdateLinks'], 10, 2); + $this->wpService->addAction('pre_post_update', [$this, 'beforeUpdateLinks'], 10, 2); //Updates the links in the post content if the post name has changed $this->wpService->addAction('post_updated', [$this, 'updateLinks'], 10, 3);