HookService::all()   B
last analyzed

Complexity

Conditions 7
Paths 1

Size

Total Lines 37
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 26
nc 1
nop 1
dl 0
loc 37
rs 8.5706
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Hooks
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2011-2022, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\Hooks\Services;
16
17
use Fisharebest\Webtrees\Registry;
18
use Fisharebest\Webtrees\Module\ModuleInterface;
19
use Fisharebest\Webtrees\Services\ModuleService;
20
use Illuminate\Database\Capsule\Manager as DB;
21
use Illuminate\Support\Collection;
22
use MyArtJaub\Webtrees\Contracts\Hooks\HookCollectorInterface;
23
use MyArtJaub\Webtrees\Contracts\Hooks\HookInterface;
24
use MyArtJaub\Webtrees\Contracts\Hooks\HookServiceInterface;
25
use MyArtJaub\Webtrees\Contracts\Hooks\ModuleHookSubscriberInterface;
26
use stdClass;
27
28
/**
29
 * Service for accessing hooks subscribed by modules.
30
 */
31
class HookService implements HookServiceInterface
32
{
33
    private ModuleService $module_service;
34
35
    /**
36
     * Constructor for HookService
37
     *
38
     * @param ModuleService $module_service
39
     */
40
    public function __construct(ModuleService $module_service)
41
    {
42
        $this->module_service = $module_service;
43
    }
44
45
    /**
46
     * {@inheritDoc}
47
     * @see \MyArtJaub\Webtrees\Contracts\Hooks\HookServiceInterface::use()
48
     */
49
    public function use(string $hook_interface): ?HookCollectorInterface
50
    {
51
        return $this->all()->get($hook_interface);
52
    }
53
54
55
    /**
56
     * Find a hook collector by its name, with or without the disabled ones.
57
     *
58
     * @param string $hook_name
59
     * @return HookCollectorInterface|null
60
     */
61
    public function find(string $hook_name, bool $include_disabled = false): ?HookCollectorInterface
62
    {
63
        return $this->all($include_disabled)
64
            ->first(fn(HookCollectorInterface $hook_collector) => $hook_collector->name() === $hook_name);
65
    }
66
67
    /**
68
     * Get all hook collectors subscribed by modules, with hooks ordered, with or without the disabled ones.
69
     *
70
     * @param bool $include_disabled
71
     * @return Collection<string, HookCollectorInterface>
72
     */
73
    public function all(bool $include_disabled = false): Collection
74
    {
75
        return Registry::cache()->array()->remember('all-hooks', function () use ($include_disabled): Collection {
76
            $hooks_info = DB::table('maj_hook_order')
77
                ->get()
78
                ->groupBy(['majho_hook_name', 'majho_module_name']);
79
80
            $hooks = $this->module_service
81
                ->findByInterface(ModuleHookSubscriberInterface::class, $include_disabled)
82
                ->flatMap(fn(ModuleHookSubscriberInterface $module) => $module->listSubscribedHooks());
83
84
            $hook_collectors = collect();
85
            $hook_instances = collect();
86
            foreach ($hooks as $hook) {
87
                if (!($hook instanceof HookInterface)) {
88
                    continue;
89
                }
90
                if ($hook instanceof HookCollectorInterface) {
91
                    $hook_collectors->put($hook->hookInterface(), $hook);
92
                } else {
93
                    $hook_instances->add($hook);
94
                }
95
            }
96
97
            foreach ($hook_collectors as $hook_interface => $hook_collector) {
98
                $hook_info = $hooks_info->get($hook_collector->name()) ?? collect();
99
                foreach (
100
                    $hook_instances->filter(
101
                        fn(HookInterface $hook): bool => $hook instanceof $hook_interface
102
                    ) as $hook_instance
103
                ) {
104
                    $hook_module_info = $hook_info->get($hook_instance->module()->name(), collect())->first();
105
                    $hook_order = $hook_module_info instanceof stdClass ? (int) $hook_module_info->majho_hook_order : 0;
106
                    $hook_collector->register($hook_instance, $hook_order);
107
                }
108
            }
109
            return $hook_collectors;
110
        });
111
    }
112
113
    /**
114
     * Update the order of the modules implementing a hook in the database.
115
     *
116
     * @param HookCollectorInterface $hook_collector
117
     * @param ModuleInterface $module
118
     * @param int $order
119
     * @return int
120
     */
121
    public function updateOrder(HookCollectorInterface $hook_collector, ModuleInterface $module, int $order): int
122
    {
123
        return DB::table('maj_hook_order')
124
            ->upsert([
125
                'majho_module_name' =>  $module->name(),
126
                'majho_hook_name'   =>  $hook_collector->name(),
127
                'majho_hook_order'  =>  $order
128
            ], ['majho_module_name', 'majho_hook_name'], ['majho_hook_order']);
129
    }
130
}
131