<?php
|
|
declare(strict_types=1);
|
|
/*
|
* This file is part of the EasyWeChatComposer.
|
*
|
* (c) 张铭阳 <mingyoungcheung@gmail.com>
|
*
|
* This source file is subject to the MIT license that is bundled
|
* with this source code in the file LICENSE.
|
*/
|
|
namespace EasyWeChatComposer;
|
|
use EasyWeChat\Kernel\Contracts\EventHandlerInterface;
|
use Pimple\Container;
|
use ReflectionClass;
|
|
class Extension
|
{
|
/**
|
* @var \Pimple\Container
|
*/
|
protected $app;
|
|
/**
|
* @var string
|
*/
|
protected $manifestPath;
|
|
/**
|
* @var array|null
|
*/
|
protected $manifest;
|
|
/**
|
* @param \Pimple\Container $app
|
*/
|
public function __construct(Container $app)
|
{
|
$this->app = $app;
|
$this->manifestPath = __DIR__.'/../extensions.php';
|
}
|
|
/**
|
* Get observers.
|
*
|
* @return array
|
*/
|
public function observers(): array
|
{
|
if ($this->shouldIgnore()) {
|
return [];
|
}
|
|
$observers = [];
|
|
foreach ($this->getManifest() as $name => $extra) {
|
$observers = array_merge($observers, $extra['observers'] ?? []);
|
}
|
|
return array_map([$this, 'listObserver'], array_filter($observers, [$this, 'validateObserver']));
|
}
|
|
/**
|
* @param mixed $observer
|
*
|
* @return bool
|
*/
|
protected function isDisable($observer): bool
|
{
|
return in_array($observer, $this->app->config->get('disable_observers', []));
|
}
|
|
/**
|
* Get the observers should be ignore.
|
*
|
* @return bool
|
*/
|
protected function shouldIgnore(): bool
|
{
|
return !file_exists($this->manifestPath) || $this->isDisable('*');
|
}
|
|
/**
|
* Validate the given observer.
|
*
|
* @param mixed $observer
|
*
|
* @return bool
|
*
|
* @throws \ReflectionException
|
*/
|
protected function validateObserver($observer): bool
|
{
|
return !$this->isDisable($observer)
|
&& (new ReflectionClass($observer))->implementsInterface(EventHandlerInterface::class)
|
&& $this->accessible($observer);
|
}
|
|
/**
|
* Determine whether the given observer is accessible.
|
*
|
* @param string $observer
|
*
|
* @return bool
|
*/
|
protected function accessible($observer): bool
|
{
|
if (!method_exists($observer, 'getAccessor')) {
|
return true;
|
}
|
|
return in_array(get_class($this->app), (array) $observer::getAccessor());
|
}
|
|
/**
|
* @param mixed $observer
|
*
|
* @return array
|
*/
|
protected function listObserver($observer): array
|
{
|
$condition = method_exists($observer, 'onCondition') ? $observer::onCondition() : '*';
|
|
return [$observer, $condition];
|
}
|
|
/**
|
* Get the easywechat manifest.
|
*
|
* @return array
|
*/
|
protected function getManifest(): array
|
{
|
if (!is_null($this->manifest)) {
|
return $this->manifest;
|
}
|
|
return $this->manifest = file_exists($this->manifestPath) ? require $this->manifestPath : [];
|
}
|
}
|