|
|
@@ -0,0 +1,143 @@
|
|
|
+<?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 : [];
|
|
|
+ }
|
|
|
+}
|