Skip to content

Commit

Permalink
Merge pull request #275 from dxw/fix/handle-non-existent-author
Browse files Browse the repository at this point in the history
Fix/handle non existent author
  • Loading branch information
RobjS authored Jan 9, 2025
2 parents bc8f3fe + cf0b5a8 commit 53a9baf
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 0 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

- If a post has an author that no longer exists, the authorship of that post is re-allocated to the user with ID matching the `archive_author` option (if that options exists)

## [6.0.2] - 2024-12-13

### Fixed
Expand Down
51 changes: 51 additions & 0 deletions app/Theme/FixNonExistentAuthors.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace GovUKBlogs\Theme;

class FixNonExistentAuthors implements \Dxw\Iguana\Registerable
{
public function register()
{
add_action('gds_byline', [$this, 'replaceAbsentAuthor']);
}

public function replaceAbsentAuthor()
{
global $post;
$post_author_id = get_post_field('post_author', $post->ID);
if ($post_author_id > 1) {
$post_author = get_user_by('id', $post_author_id);
if (!($post_author)) {
error_log("author of post {$post->ID} is deleted user $post_author_id", 0);
add_filter('wp_insert_post_data', [$this, 'setArchiveAuthor'], 99, 2);
wp_update_post($post);
}
}
}

public function setArchiveAuthor($postData, $postArray)
{
$fix_types = ["page", "post", "attachment"];

if (!in_array($postData['post_type'], $fix_types)) {
return $postData;
}

$archive_user_option = get_network_option(null, 'archive_author');

if (!empty($archive_user_option)) {
if (is_int($archive_user_option)) {
$archive_author_id = $archive_user_option;
} elseif (is_string($archive_user_option) && ctype_digit($archive_user_option)) {
$archive_author_id = intval($archive_user_option);
}
if (!empty($archive_author_id)) {
$postData['post_author'] = $archive_author_id;
if (taxonomy_exists('author')) {
wp_delete_object_term_relationships($postArray['ID'], 'author');
}
}
}
return $postData;
}
}
1 change: 1 addition & 0 deletions app/di.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
));
$registrar->addInstance(new \GovUKBlogs\Theme\ThemeSetup());
$registrar->addInstance(new \GovUKBlogs\Theme\OldRootsCleanup());
$registrar->addInstance(new \GovUKBlogs\Theme\FixNonExistentAuthors());
1 change: 1 addition & 0 deletions lib/byline.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Display the author for a post, using coauthors if available and falling back to the WordPress user if not.
function gds_byline()
{
do_action('gds_byline');
?>
<span class="govuk-visually-hidden">Posted by: </span>
<?php
Expand Down
153 changes: 153 additions & 0 deletions spec/theme/fix_not_existent_authors.spec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?php

describe(\GovUKBlogs\Theme\FixNonExistentAuthors::class, function () {
beforeEach(function () {
$this->fixNonExistentAuthors = new \GovUKBlogs\Theme\FixNonExistentAuthors();
});

it('implements the Registerable interface', function () {
expect($this->fixNonExistentAuthors)->toBeAnInstanceOf(\Dxw\Iguana\Registerable::class);
});

describe('->register()', function () {
it('adds the action', function () {
allow('add_action')->toBeCalled();
expect('add_action')->toBeCalled()->once()->with('gds_byline', [$this->fixNonExistentAuthors, 'replaceAbsentAuthor']);
$this->fixNonExistentAuthors->register();
});
});

describe('->replaceAbsentAuthor()', function () {
context('the post author ID is 1', function () {
it('does nothing', function () {
global $post;
$post = (object) [
"ID" => 123
];
allow('get_post_field')->toBeCalled()->andReturn(1);
expect('wp_update_post')->not->toBeCalled();

$this->fixNonExistentAuthors->replaceAbsentAuthor();
});
});
context('the post author ID is greater than 1', function () {
context('but the user exists', function () {
it('does nothing', function () {
global $post;
$post = (object) [
"ID" => 123
];
allow('get_post_field')->toBeCalled()->andReturn(2);
allow('get_user_by')->toBeCalled()->andReturn((object) [
"ID" => 2,
"user_login" => "valid_user"
]);
expect('wp_update_post')->not->toBeCalled();

$this->fixNonExistentAuthors->replaceAbsentAuthor();
});
});
context('and the user does not exist', function () {
it('adds the filter and calls update_post', function () {
global $post;
$post = (object) [
"ID" => 123
];
allow('get_post_field')->toBeCalled()->andReturn(2);
allow('get_user_by')->toBeCalled()->andReturn(false);
allow('add_filter')->toBeCalled();
allow('error_log')->toBeCalled();
expect('error_log')->toBeCalled()->once()->with('author of post 123 is deleted user 2', 0);
expect('add_filter')->toBeCalled()->once()->with('wp_insert_post_data', [$this->fixNonExistentAuthors, 'setArchiveAuthor'], 99, 2);
allow('wp_update_post')->toBeCalled();
expect('wp_update_post')->toBeCalled()->once();

$this->fixNonExistentAuthors->replaceAbsentAuthor();
});
});
});
});

describe('->setArchiveAuthor()', function () {
context('the post is not one of the types we want to fix', function () {
it('returns the post data unamended', function () {
$postData = [
'post_type' => 'custom_post_type',
'post_author' => 123
];
expect('get_network_option')->not->toBeCalled();

$result = $this->fixNonExistentAuthors->setArchiveAuthor($postData, []);

expect($result)->toEqual($postData);
});
});
context('the post is one of the type we want to fix', function () {
beforeEach(function () {
$this->postData = [
'post_type' => 'post',
'post_author' => 123
];
});
context('but the archive_author option is not set', function () {
it('returns the post data unamended', function () {
allow('get_network_option')->toBeCalled()->andReturn(false);

$result = $this->fixNonExistentAuthors->setArchiveAuthor($this->postData, []);

expect($result)->toEqual($this->postData);
});
});
context('and the archive_author option is an integer', function () {
it('amends the post data to set the post_author to the archive_author value', function () {
allow('get_network_option')->toBeCalled()->andReturn(456);
allow('taxonomy_exists')->toBeCalled()->andReturn(false);

$result = $this->fixNonExistentAuthors->setArchiveAuthor($this->postData, []);

expect($result)->toEqual([
'post_type' => 'post',
'post_author' => 456
]);
});
});
context('and the archive_author option is a string containing only an integer', function () {
it('amends the post data to set the post_author to the archive_author value', function () {
allow('get_network_option')->toBeCalled()->andReturn('456');
allow('taxonomy_exists')->toBeCalled()->andReturn(false);

$result = $this->fixNonExistentAuthors->setArchiveAuthor($this->postData, []);

expect($result)->toEqual([
'post_type' => 'post',
'post_author' => 456
]);
});
});
context('and the archive_author option is a string containing non-numeric characters', function () {
it('returns the post data unamended', function () {
allow('get_network_option')->toBeCalled()->andReturn('456foo');

$result = $this->fixNonExistentAuthors->setArchiveAuthor($this->postData, []);

expect($result)->toEqual($this->postData);
});
});
context('and the "author" taxonomy exists, indicating that co-authors is in use', function () {
it('removes any existing co-author relationships with this post, as well as amending the author ID', function () {
allow('get_network_option')->toBeCalled()->andReturn(456);
allow('taxonomy_exists')->toBeCalled()->andReturn(true);
allow('wp_delete_object_term_relationships')->toBeCalled();
expect('wp_delete_object_term_relationships')->toBeCalled()->once()->with(123, 'author');

$result = $this->fixNonExistentAuthors->setArchiveAuthor($this->postData, ['ID' => 123]);

expect($result)->toEqual([
'post_type' => 'post',
'post_author' => 456
]);
});
});
});
});
});

0 comments on commit 53a9baf

Please sign in to comment.