Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1666d44
Failing test
srtfisher Mar 5, 2025
aa0f7ed
Switch to class created with eval
srtfisher Mar 5, 2025
262f13c
Remove unused classes
srtfisher Mar 5, 2025
e407064
CHANGELOG typo
srtfisher Mar 5, 2025
eaa93d1
Ignore unset.possiblyHookedProperty
srtfisher Mar 5, 2025
75612e7
Install CAP and byline manager
srtfisher Mar 5, 2025
16bc155
Merge branch 'feature/dynamic-model' into feature/co-authors-plus
srtfisher Mar 5, 2025
98fd93c
WIP
srtfisher Mar 5, 2025
a645431
Leaving for today
srtfisher Mar 5, 2025
4bea7e5
Wrapping up Co authors plus factory
srtfisher Mar 6, 2025
bffdd55
Test fix
srtfisher Mar 6, 2025
a422def
CHANGELOG
srtfisher Mar 6, 2025
202dc73
CHANGELOG and indenting
srtfisher Mar 6, 2025
6e1dba8
Merge branch '1.x' into feature/dynamic-model
srtfisher Mar 6, 2025
1bc6a13
Merge branch 'feature/dynamic-model' into feature/co-authors-plus
srtfisher Mar 6, 2025
2b3b78e
Fix changelog indenting
srtfisher Mar 6, 2025
056915a
Fix changelog indenting
srtfisher Mar 6, 2025
eddb520
Remove todo
srtfisher Mar 6, 2025
e5a16bc
Add method for creating a post with cap authors
srtfisher Mar 6, 2025
f81e3a5
Stubbing out byline manager factory
srtfisher Mar 6, 2025
2268e54
Add byline manager factory
srtfisher Mar 6, 2025
f304300
CHANGELOG
srtfisher Mar 6, 2025
7c77664
Forward directly and allow deprecations
srtfisher Mar 6, 2025
3beb063
Merge branch '1.x' into feature/co-authors-plus
srtfisher Mar 7, 2025
5adf2e3
Allow notice
srtfisher Mar 7, 2025
7425cb7
Merge branch 'feature/co-authors-plus' of github.com:alleyinteractive…
srtfisher Mar 7, 2025
cc13e49
Adding convertNoticesToExceptions
srtfisher Mar 7, 2025
91b10ca
Fix notice with CAP
srtfisher Mar 7, 2025
1581c52
Split out unit testing for phpunit 9 to have a proper config
srtfisher Mar 7, 2025
d5038a0
Merging in 1.x
srtfisher Mar 7, 2025
b00ff55
Remove unset.possiblyHookedProperty
srtfisher Mar 7, 2025
ca4f4db
Simply
srtfisher Mar 7, 2025
b5fa514
Fix commands
srtfisher Mar 7, 2025
eff1204
Ignore error
srtfisher Mar 7, 2025
ef1ad11
Ensure user URL is not over 100
srtfisher Mar 7, 2025
84e4ed9
Fix step name
srtfisher Mar 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/phpstan-baseline.neon export-ignore
/phpstan.neon export-ignore
/phpunit.xml export-ignore
/phpunit-9.xml export-ignore
/tests export-ignore

#
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
if: github.event.pull_request.draft == false
timeout-minutes: 10
runs-on: ubuntu-latest
name: "Lint Tests"
name: "Composer and Monorepo Validate"
steps:
- uses: actions/checkout@v4

Expand All @@ -30,7 +30,7 @@ jobs:
php-version: '8.4'
skip-services: 'true'
skip-wordpress-install: 'true'
test-command: 'composer monorepo-validate'
test-command: 'composer validate --strict && composer monorepo-validate'
lint-tests:
if: github.event.pull_request.draft == false
timeout-minutes: 10
Expand Down Expand Up @@ -77,7 +77,8 @@ jobs:
install-command: composer update --${{ matrix.dependencies }} --prefer-dist --no-interaction --no-progress
php-version: '${{ matrix.php }}'
skip-wordpress-install: 'true'
test-command: 'composer phpunit'
# Only run PHPUnit for the lowest dependencies.
test-command: ${{ matrix.dependencies == 'prefer-lowest' && 'composer phpunit-9' || 'composer phpunit' }}
wordpress-host: 'false'
wordpress-multisite: '${{ matrix.multisite }}'
wordpress-version: '${{ matrix.wordpress }}'
Expand Down
14 changes: 10 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added a unit testing factory for Byline Manager profiles and Co-Authors-Plus guest authors.

### Changed

- Passing a `\Stringable` as a model attribute will now be cast to a string
before being set on the model.
- Added `with_debug()` and `with_multisite()` methods to the installation manager.

### Fixed
Expand Down Expand Up @@ -96,9 +102,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
by setting the `MANTLE_EXPERIMENTAL_TESTING_USE_HOME_URL_HOST` environment
variable.

Once enabled, the home URL will be used as the base URL for testing rather
the hard-coded `WP_TESTS_DOMAIN`. It will also infer the HTTPS status from
the home URL.
Once enabled, the home URL will be used as the base URL for testing rather
the hard-coded `WP_TESTS_DOMAIN`. It will also infer the HTTPS status from
the home URL.
- Added `with_option()`/`with_home_url()`/`with_site_url()` methods to the installation manager.
- Add a `without_local_object_cache()` method to prevent the `object-cache.php` drop-in from being loaded locally.
- Added a better `dump()` method to the response object when testing HTTP
Expand All @@ -111,7 +117,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Upgraded to Symfony 7.0 packages.
- Disable `spatie/once`'s cache if found during unit testing.
- Ensure that the `QUERY_STRING` server variable is set when testing HTTP
requests.
requests.

### Fixed

Expand Down
5 changes: 2 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,14 @@
"phpcs": "phpcs --standard=./phpcs.xml .",
"phpstan": "phpstan --memory-limit=1536M",
"phpunit:multisite": "WP_MULTISITE=1 phpunit",
"phpunit-9": "phpunit --configuration=phpunit-9.xml",
"phpunit": "phpunit",
"rector:fix": "rector process",
"rector": "rector process --dry-run",
"release:patch": "monorepo-builder release patch --ansi",
"release": "monorepo-builder release --ansi",
"test": [
"@phpcs",
"@phpstan",
"@rector",
"@lint",
"@phpunit"
]
},
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ parameters:
identifier: require.fileNotFound
-
identifier: requireOnce.fileNotFound
# Will be fixed in PHPStan soon.
-
identifier: unset.possiblyHookedProperty
-
Expand Down
18 changes: 18 additions & 0 deletions phpunit-9.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="tests/bootstrap.php"
backupGlobals="false"
colors="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.6/phpunit.xsd"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
convertDeprecationsToExceptions="true"
>
<testsuites>
<testsuite name="mantle-framework">
<directory suffix="Test.php">./tests/</directory>
</testsuite>
</testsuites>
</phpunit>
4 changes: 3 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
bootstrap="tests/bootstrap.php"
backupGlobals="false"
colors="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.5/phpunit.xsd"
displayDetailsOnTestsThatTriggerDeprecations="true"
displayDetailsOnTestsThatTriggerWarnings="true"
failOnNotice="true"
failOnPhpunitDeprecation="true"
failOnWarning="true"
failOnDeprecation="true"
>
<testsuites>
Expand Down
18 changes: 18 additions & 0 deletions src/mantle/database/factory/class-factory-container.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ class Factory_Container {
*/
public Blog_Factory $blog;

/**
* Byline Manager Factory
*
* @var Plugins\Byline_Manager_Factory<\Mantle\Database\Model\Post, \Byline_Manager\Models\Profile, \Byline_Manager\Models\Profile>
*/
public Plugins\Byline_Manager_Factory $byline_manager_profile;

/**
* Co Author Guest Author Factory
*
* @var Plugins\Co_Authors_Plus_Factory<\Mantle\Database\Model\Post, \stdClass, \stdClass>
*/
public Plugins\Co_Authors_Plus_Factory $cap_guest_author;

/**
* Category Factory
*
Expand Down Expand Up @@ -115,6 +129,10 @@ public function __construct( Container $container ) {
$this->blog = $container->make( Blog_Factory::class );
$this->network = $container->make( Network_Factory::class );
}

// Plugin-specific factories.
$this->byline_manager_profile = $container->make( Plugins\Byline_Manager_Factory::class );
$this->cap_guest_author = $container->make( Plugins\Co_Authors_Plus_Factory::class );
}

/**
Expand Down
6 changes: 2 additions & 4 deletions src/mantle/database/factory/class-factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,8 @@ public function as_objects() {
* Create a new factory instance with middleware.
*
* @param callable(array $args, \Closure $next): mixed $middleware Middleware to run the factory through.
* @return static
*/
public function with_middleware( callable $middleware ) {
public function with_middleware( callable $middleware ): static {
return tap(
clone $this,
fn ( Factory $factory ) => $factory->middleware = $this->middleware->merge( $middleware ),
Expand Down Expand Up @@ -189,9 +188,8 @@ public function get_model(): string {
* middleware but supports returning an array of attributes vs a closure.
*
* @param (callable(array<string, mixed>): array<string, mixed>|array<string, mixed>) $state The state transformation.
* @return static
*/
public function state( array|callable $state ) {
public function state( array|callable $state ): static {
return $this->with_middleware(
function ( array $args, Closure $next ) use ( $state ) {
$args = array_merge(
Expand Down
8 changes: 7 additions & 1 deletion src/mantle/database/factory/class-post-factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
* @extends Factory<TModel, TObject, TReturnValue>
*/
class Post_Factory extends Factory {
use Concerns\With_Byline_Manager_Profiles;
use Concerns\With_Guest_Authors;
use Concerns\With_Meta;

/**
Expand Down Expand Up @@ -92,7 +94,11 @@ public function with_terms( ...$terms ): static {
$terms = collect( $terms )->all();

return $this->with_middleware(
fn ( array $args, Closure $next ) => $next( $args )->set_terms( $terms, append: $this->append_terms, create: $this->create_terms ),
fn ( array $args, Closure $next ) => $next( $args )->set_terms(
terms: $terms,
append: $this->append_terms,
create: $this->create_terms,
),
);
}

Expand Down
18 changes: 17 additions & 1 deletion src/mantle/database/factory/class-user-factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Mantle\Database\Model\User;

use function Mantle\Support\Helpers\get_user_object;
use function Mantle\Support\Helpers\stringable;

/**
* User Factory
Expand All @@ -36,12 +37,18 @@ class User_Factory extends Factory {
* @return array<string, mixed>
*/
public function definition(): array {
$first_name = $this->faker->firstName();
$last_name = $this->faker->lastName();

return [
'description' => $this->faker->sentence(),
'first_name' => $first_name,
'last_name' => $last_name,
'role' => 'subscriber',
'user_email' => $this->faker->email(),
'user_login' => $this->faker->userName(),
'user_login' => stringable( "{$first_name} {$last_name}" )->slugify(),
'user_pass' => 'password',
'user_url' => substr( $this->faker->url(), 0, 100 ),
];
}

Expand All @@ -54,4 +61,13 @@ public function definition(): array {
public function get_object_by_id( int $object_id ) {
return $this->as_models ? $this->model::find( $object_id ) : get_user_object( $object_id );
}

/**
* Create a user with a specific role.
*
* @param string $role The role to assign to the user.
*/
public function with_role( string $role ): static {
return $this->state( [ 'role' => $role ] );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php
/**
* With_Byline_Manager_Profiles trait file
*
* @package Mantle
*/

namespace Mantle\Database\Factory\Concerns;

use Byline_Manager\Models\Profile;
use Byline_Manager\Utils;
use Closure;
use Mantle\Database\Factory\Plugins\Byline_Manager_Factory;
use WP_User;

use function Mantle\Support\Helpers\collect;

/**
* Manage Byline Manager authors on posts.
*
* @phpstan-type BylineManagerEntry array{type: string, attrs: array<string, mixed>}
*
* @mixin \Mantle\Database\Factory\Post_Factory
*/
trait With_Byline_Manager_Profiles {
/**
* Add a bylines to a post with Byline Manager.
*
* @throws \RuntimeException If Byline Manager is not installed or initialized.
*
* @param string|int|Profile|WP_User ...$authors The profile ID/object, WP_User object, or text string.
*/
public function with_byline_manager_authors( ...$authors ): static {
if ( ! class_exists( Profile::class ) ) {
throw new \RuntimeException( 'Byline Manager is not installed.' );
}

return $this->with_middleware( function ( array $args, Closure $next ) use ( $authors ) {
/** @var \Mantle\Database\Model\Post $profile */
$profile = $next( $args );

Utils::set_post_byline(
$profile->id(),
[
'byline_entries' => collect( $authors )
->map( $this->resolve_byline_manager_entry( ... ) )
->filter()
->values()
->all(),
],
);

return $profile;
} );
}

/**
* Resolve the author to the underlying term ID for the Profile.
*
* @param string|int|Profile|WP_User $item The profile ID/object, WP_User object, or text string.
* @return array
* @phpstan-return BylineManagerEntry
*/
protected function resolve_byline_manager_entry( string|int|WP_User|Profile $item ): ?array {
if ( is_string( $item ) ) {
return [
'type' => 'text',
'atts' => [
'text' => $item,
],
];
}

if ( is_int( $item ) || $item instanceof Profile ) {
$profile = $item instanceof Profile ? $item : Profile::get_by_post( $item );
} elseif ( $item instanceof WP_User ) {
$profile = Byline_Manager_Factory::get_byline_manager_profile_by_user_id( $item->ID, create: true );
}

if ( empty( $profile ) ) {
return null;
}

return [
'type' => 'byline_id',
'atts' => [
'byline_id' => $profile->byline_id,
],
];
}
}
Loading
Loading