123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- <?php
- declare(strict_types=1);
- /**
- * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2016 ownCloud GmbH.
- * SPDX-License-Identifier: AGPL-3.0-only
- */
- namespace OCA\DAV\AppInfo;
- use OC\ServerContainer;
- use OCA\DAV\CalDAV\AppCalendar\AppCalendarPlugin;
- use OCA\DAV\CalDAV\Integration\ICalendarProvider;
- use OCA\DAV\CardDAV\Integration\IAddressBookProvider;
- use OCP\App\IAppManager;
- use OCP\AppFramework\QueryException;
- use Sabre\DAV\Collection;
- use Sabre\DAV\ServerPlugin;
- use function array_map;
- use function class_exists;
- use function is_array;
- /**
- * Manager for DAV plugins from apps, used to register them
- * to the Sabre server.
- */
- class PluginManager {
- /**
- * App plugins
- *
- * @var ServerPlugin[]
- */
- private $plugins = [];
- /**
- * App collections
- *
- * @var Collection[]
- */
- private $collections = [];
- /**
- * Address book plugins
- *
- * @var IAddressBookProvider[]
- */
- private $addressBookPlugins = [];
- /**
- * Calendar plugins
- *
- * @var ICalendarProvider[]
- */
- private $calendarPlugins = [];
- /** @var bool */
- private $populated = false;
- /**
- * Contstruct a PluginManager
- *
- * @param ServerContainer $container server container for resolving plugin classes
- * @param IAppManager $appManager app manager to loading apps and their info
- */
- public function __construct(
- private ServerContainer $container,
- private IAppManager $appManager,
- ) {
- }
- /**
- * Returns an array of app-registered plugins
- *
- * @return ServerPlugin[]
- */
- public function getAppPlugins() {
- $this->populate();
- return $this->plugins;
- }
- /**
- * Returns an array of app-registered collections
- *
- * @return array
- */
- public function getAppCollections() {
- $this->populate();
- return $this->collections;
- }
- /**
- * @return IAddressBookProvider[]
- */
- public function getAddressBookPlugins(): array {
- $this->populate();
- return $this->addressBookPlugins;
- }
- /**
- * Returns an array of app-registered calendar plugins
- *
- * @return ICalendarProvider[]
- */
- public function getCalendarPlugins():array {
- $this->populate();
- return $this->calendarPlugins;
- }
- /**
- * Retrieve plugin and collection list and populate attributes
- */
- private function populate(): void {
- if ($this->populated) {
- return;
- }
- $this->populated = true;
- $this->calendarPlugins[] = $this->container->get(AppCalendarPlugin::class);
- foreach ($this->appManager->getInstalledApps() as $app) {
- // load plugins and collections from info.xml
- $info = $this->appManager->getAppInfo($app);
- if (!isset($info['types']) || !in_array('dav', $info['types'], true)) {
- continue;
- }
- $plugins = $this->loadSabrePluginsFromInfoXml($this->extractPluginList($info));
- foreach ($plugins as $plugin) {
- $this->plugins[] = $plugin;
- }
- $collections = $this->loadSabreCollectionsFromInfoXml($this->extractCollectionList($info));
- foreach ($collections as $collection) {
- $this->collections[] = $collection;
- }
- $addresbookPlugins = $this->loadSabreAddressBookPluginsFromInfoXml($this->extractAddressBookPluginList($info));
- foreach ($addresbookPlugins as $addresbookPlugin) {
- $this->addressBookPlugins[] = $addresbookPlugin;
- }
- $calendarPlugins = $this->loadSabreCalendarPluginsFromInfoXml($this->extractCalendarPluginList($info));
- foreach ($calendarPlugins as $calendarPlugin) {
- $this->calendarPlugins[] = $calendarPlugin;
- }
- }
- }
- /**
- * @param array $array
- * @return string[]
- */
- private function extractPluginList(array $array): array {
- if (isset($array['sabre']) && is_array($array['sabre'])) {
- if (isset($array['sabre']['plugins']) && is_array($array['sabre']['plugins'])) {
- if (isset($array['sabre']['plugins']['plugin'])) {
- $items = $array['sabre']['plugins']['plugin'];
- if (!is_array($items)) {
- $items = [$items];
- }
- return $items;
- }
- }
- }
- return [];
- }
- /**
- * @param array $array
- * @return string[]
- */
- private function extractCollectionList(array $array): array {
- if (isset($array['sabre']) && is_array($array['sabre'])) {
- if (isset($array['sabre']['collections']) && is_array($array['sabre']['collections'])) {
- if (isset($array['sabre']['collections']['collection'])) {
- $items = $array['sabre']['collections']['collection'];
- if (!is_array($items)) {
- $items = [$items];
- }
- return $items;
- }
- }
- }
- return [];
- }
- /**
- * @param array $array
- * @return string[]
- */
- private function extractAddressBookPluginList(array $array): array {
- if (!isset($array['sabre']) || !is_array($array['sabre'])) {
- return [];
- }
- if (!isset($array['sabre']['address-book-plugins']) || !is_array($array['sabre']['address-book-plugins'])) {
- return [];
- }
- if (!isset($array['sabre']['address-book-plugins']['plugin'])) {
- return [];
- }
- $items = $array['sabre']['address-book-plugins']['plugin'];
- if (!is_array($items)) {
- $items = [$items];
- }
- return $items;
- }
- /**
- * @param array $array
- * @return string[]
- */
- private function extractCalendarPluginList(array $array): array {
- if (isset($array['sabre']) && is_array($array['sabre'])) {
- if (isset($array['sabre']['calendar-plugins']) && is_array($array['sabre']['calendar-plugins'])) {
- if (isset($array['sabre']['calendar-plugins']['plugin'])) {
- $items = $array['sabre']['calendar-plugins']['plugin'];
- if (!is_array($items)) {
- $items = [$items];
- }
- return $items;
- }
- }
- }
- return [];
- }
- private function createClass(string $className): object {
- try {
- return $this->container->get($className);
- } catch (QueryException $e) {
- if (class_exists($className)) {
- return new $className();
- }
- }
- throw new \Exception('Could not load ' . $className, 0, $e);
- }
- /**
- * @param string[] $classes
- * @return ServerPlugin[]
- * @throws \Exception
- */
- private function loadSabrePluginsFromInfoXml(array $classes): array {
- return array_map(function (string $className): ServerPlugin {
- $instance = $this->createClass($className);
- if (!($instance instanceof ServerPlugin)) {
- throw new \Exception('Sabre server plugin ' . $className . ' does not implement the ' . ServerPlugin::class . ' interface');
- }
- return $instance;
- }, $classes);
- }
- /**
- * @param string[] $classes
- * @return Collection[]
- */
- private function loadSabreCollectionsFromInfoXml(array $classes): array {
- return array_map(function (string $className): Collection {
- $instance = $this->createClass($className);
- if (!($instance instanceof Collection)) {
- throw new \Exception('Sabre collection plugin ' . $className . ' does not implement the ' . Collection::class . ' interface');
- }
- return $instance;
- }, $classes);
- }
- /**
- * @param string[] $classes
- * @return IAddressBookProvider[]
- */
- private function loadSabreAddressBookPluginsFromInfoXml(array $classes): array {
- return array_map(function (string $className): IAddressBookProvider {
- $instance = $this->createClass($className);
- if (!($instance instanceof IAddressBookProvider)) {
- throw new \Exception('Sabre address book plugin class ' . $className . ' does not implement the ' . IAddressBookProvider::class . ' interface');
- }
- return $instance;
- }, $classes);
- }
- /**
- * @param string[] $classes
- * @return ICalendarProvider[]
- */
- private function loadSabreCalendarPluginsFromInfoXml(array $classes): array {
- return array_map(function (string $className): ICalendarProvider {
- $instance = $this->createClass($className);
- if (!($instance instanceof ICalendarProvider)) {
- throw new \Exception('Sabre calendar plugin class ' . $className . ' does not implement the ' . ICalendarProvider::class . ' interface');
- }
- return $instance;
- }, $classes);
- }
- }
|