Skip to content

Commit

Permalink
ARW-1019 bulk edit
Browse files Browse the repository at this point in the history
  • Loading branch information
speckmaier committed Sep 30, 2024
1 parent 3a3ce30 commit 9b3d2cb
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/BulkEdit/Attribute/AsBulkEditContainer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace VAF\WP\Framework\BulkEdit\Attribute;

use Attribute;

/**
* Service tag to autoconfigure bulk edit container.
*/
#[Attribute(Attribute::TARGET_CLASS)]
class AsBulkEditContainer
{
}
17 changes: 17 additions & 0 deletions src/BulkEdit/Attribute/BulkEdit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace VAF\WP\Framework\BulkEdit\Attribute;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
final class BulkEdit
{
public function __construct(
public readonly string $title,
public readonly string|array|null $postTypes = null,
public readonly string|null $supporting = null,
) {
}

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

namespace VAF\WP\Framework\BulkEdit;

class EmptySupportingPostTypesException extends \RuntimeException
{

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

namespace VAF\WP\Framework\BulkEdit;

use VAF\WP\Framework\Kernel\WordpressKernel;

final class Loader
{
public function __construct(private readonly WordpressKernel $kernel, private readonly array $bulkeditContainer)
{
}

public function registerMetaboxes(): void
{
foreach ($this->bulkeditContainer as $serviceId => $bulkeditContainer) {
foreach ($bulkeditContainer as $data) {

add_action('add_meta_boxes', function () use ($data, $serviceId) {
$this->registerBulkEditField($serviceId, $data);


try {
} catch (EmptySupportingPostTypesException) {
// should only show up on supporting post types but none are registered and registering with
//empty array would result in showing up on all post types
}
}, 5);
}

}
}

public function registerBulkEditField($serviceId, $data)
{
$methodName = $data['method'];

add_action('admin_init', function () use ($data) {
$post_types = PostTypeList::fromPostTypes($data['postTypes'])->withSupporting($data['supporting'], fn($feature) => get_post_types_by_support($feature))
->postTypes();

foreach ($post_types as $post_type => $label) {
add_action("manage_{$post_type}_posts_columns", function ($columns) use ($data) {
return [
...$columns,
$data['name'] => $data['title'],
];
});

add_filter("manage_edit-{$post_type}_columns", function ($columns) use ($data) {
return [
...$columns,
$data['name'] => $data['title'],
];
}, 9999);
}
});

add_action('bulk_edit_custom_box', function ($columnName, $serviceId, $data) {
if ($columnName !== $data['name']) {
return;
}

$methodName = $data['method'];
echo $this->kernel->getContainer()->get($serviceId)->$methodName();
});

add_action('hidden_columns', function ($columns, $data) {
return [
...$columns,
$data['name'],
];
});
}
}
65 changes: 65 additions & 0 deletions src/BulkEdit/LoaderCompilerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace VAF\WP\Framework\BulkEdit;

use ReflectionClass;
use ReflectionMethod;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use VAF\WP\Framework\Metabox\Attribute\Metabox;
use VAF\WP\Framework\Slug;

final class LoaderCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (!$container->has('bulkedit.loader')) {
return;
}

$loaderDefinition = $container->findDefinition('bulkedit.loader');

$bulkeditContainerServices = $container->findTaggedServiceIds('bulkedit.container');

$bulkeditContainerData = [];
foreach ($bulkeditContainerServices as $id => $tags) {
$definition = $container->findDefinition($id);
$definition->setPublic(true);
$bulkeditContainerData[$id] = $this->getBulkEditContainerData($definition->getClass(), $container);
}
$loaderDefinition->setArgument('$bulkeditContainer', $bulkeditContainerData);
}

private function getBulkEditContainerData(string $class, ContainerBuilder $container): array
{
$data = [];

$reflection = new ReflectionClass($class);
foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
$methodName = $method->getName();

// Check if the Metabox attribute is present
$attributes = $method->getAttributes(Metabox::class);
if (empty($attributes)) {
continue;
}

foreach ($attributes as $attribute) {
/**
* @var BulkEdit $instance
*/
$instance = $attribute->newInstance();

$data[] = [
'method' => $methodName,
'name' => (string)Slug::fromName($instance->title),
'title' => $instance->title,
'postTypes' => $instance->postTypes,
'supporting' => $instance->supporting,
];
}
}

return $data;
}
}
50 changes: 50 additions & 0 deletions src/BulkEdit/PostTypeList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace VAF\WP\Framework\BulkEdit;

use VAF\WP\Framework\Metabox\EmptySupportingScreensException;

class PostTypeList
{

private string|array|null $postTypes;
private ?string $feature;
private array $supportingPostTypes = [];

public static function fromPostTypes(string|array|null $screen): self
{
$screenList = new static();

$screenList->postTypes = $screen;

return $screenList;
}

public function withSupporting(string|null $feature, callable $postTypesFromFeature): self
{
$screenList = clone $this;

$screenList->feature = $feature;
$screenList->supportingPostTypes = $feature === null ? [] : $postTypesFromFeature($feature);

return $screenList;
}

public function postTypes(): string|array|null
{
if ($this->feature === null) {
return $this->postTypes;
}

if($this->postTypes === null && empty($this->supportingPostTypes)) {
throw new EmptySupportingPostTypesException();
}

if($this->postTypes === null) {
return $this->supportingPostTypes;
}

return [$this->postTypes, ...$this->supportingPostTypes];
}

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

namespace VAF\WP\Framework;

class Slug
{

private string $name;

public static function fromName(string $name): self
{
$slug = new static();

$slug->name = $name;

return $slug;
}

public function __toString(): string
{
return preg_replace(
'~[^a-zA-Z]~',
'-',
strtolower(
$this->name,
),
);
}
}
30 changes: 30 additions & 0 deletions tests/Unit/SlutTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace VAF\WP\FrameworkTests\Unit;

use VAF\WP\Framework\Slug;
use VAF\WP\FrameworkTests\TestCase;

class SlutTest extends TestCase
{

/**
* @test
*/
public function should_keep_a_to_z()
{
$slug = Slug::fromName('abcdefghijklmnopqrstuvwxyz');

$this->assertEquals('abcdefghijklmnopqrstuvwxyz', (string)$slug);
}

/**
* @test
*/
public function should_keep_capital_a_to_z()
{
$slug = Slug::fromName('ABCDEFGHIJKLMNOPQRSTUVWXYZ');

$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', (string)$slug);
}
}

0 comments on commit 9b3d2cb

Please sign in to comment.