diff --git a/src/Core/Addon/AddonInfo.php b/src/Core/Addon/AddonInfo.php index ce5f07fc0f..8b44b6f841 100644 --- a/src/Core/Addon/AddonInfo.php +++ b/src/Core/Addon/AddonInfo.php @@ -14,6 +14,76 @@ namespace Friendica\Core\Addon; */ final class AddonInfo { + /** + * Parse addon comment in search of addon infos. + * + * like + * \code + * * Name: addon + * * Description: An addon which plugs in + * . * Version: 1.2.3 + * * Author: John + * * Author: Jane + * * Maintainer: Jess without link + * * Maintainer: Robin + * * Status: in development + * \endcode + * + * @internal Never create this object by yourself, use `Friendica\Core\Addon\AddonHelper::getAddonInfo()` instead. + * @see Friendica\Core\Addon\AddonHelper::getAddonInfo() + * + * @param string $addonId the name of the addon + * @param string $raw The raw file content + */ + public static function fromString(string $addonId, string $raw): self + { + $data = [ + 'id' => $addonId, + ]; + + $result = preg_match("|/\*.*\*/|msU", $raw, $m); + + if ($result === false || $result === 0) { + return self::fromArray($data); + } + + $ll = explode("\n", $m[0]); + + foreach ($ll as $l) { + $l = trim($l, "\t\n\r */"); + if ($l !== '') { + $addon_info = array_map('trim', explode(":", $l, 2)); + if (count($addon_info) < 2) { + continue; + } + + list($type, $v) = $addon_info; + $type = strtolower($type); + + if ($type === 'author' || $type === 'maintainer') { + $r = preg_match("|([^<]+)<([^>]+)>|", $v, $m); + if ($r === false || $r === 0) { + $data[$type][] = ['name' => trim($v)]; + } else { + $data[$type][] = ['name' => trim($m[1]), 'link' => $m[2]]; + } + } else { + $data[$type] = $v; + } + } + } + + // rename author to authors + $data['authors'] = $data['author']; + unset($data['author']); + + // rename maintainer to maintainers + $data['maintainers'] = $data['maintainer']; + unset($data['maintainer']); + + return self::fromArray($data); + } + /** * @internal Never create this object by yourself, use `Friendica\Core\Addon\AddonHelper::getAddonInfo()` instead. * @@ -21,25 +91,21 @@ final class AddonInfo */ public static function fromArray(array $info): self { - $id = array_key_exists('id', $info) ? (string) $info['id'] : ''; - $name = array_key_exists('name', $info) ? (string) $info['name'] : ''; - $description = array_key_exists('description', $info) ? (string) $info['description'] : ''; - $authors = array_key_exists('authors', $info) ? self::parseContributors($info['authors']) : []; - $maintainers = array_key_exists('maintainers', $info) ? self::parseContributors($info['maintainers']) : []; - $version = array_key_exists('version', $info) ? (string) $info['version'] : ''; - $status = array_key_exists('status', $info) ? (string) $info['status'] : ''; + $addonInfo = new self(); + $addonInfo->id = array_key_exists('id', $info) ? (string) $info['id'] : ''; + $addonInfo->name = array_key_exists('name', $info) ? (string) $info['name'] : ''; + $addonInfo->description = array_key_exists('description', $info) ? (string) $info['description'] : ''; + $addonInfo->authors = array_key_exists('authors', $info) ? self::parseContributors($info['authors']) : []; + $addonInfo->maintainers = array_key_exists('maintainers', $info) ? self::parseContributors($info['maintainers']) : []; + $addonInfo->version = array_key_exists('version', $info) ? (string) $info['version'] : ''; + $addonInfo->status = array_key_exists('status', $info) ? (string) $info['status'] : ''; - return new self( - $id, - $name, - $description, - $authors, - $maintainers, - $version, - $status - ); + return $addonInfo; } + /** + * @param mixed $entries + */ private static function parseContributors($entries): array { if (!is_array($entries)) { @@ -85,22 +151,7 @@ final class AddonInfo private string $status = ''; - private function __construct( - string $id, - string $name, - string $description, - array $authors, - array $maintainers, - string $version, - string $status - ) { - $this->id = $id; - $this->name = $name; - $this->description = $description; - $this->authors = $authors; - $this->maintainers = $maintainers; - $this->version = $version; - $this->status = $status; + private function __construct() { } public function getId(): string diff --git a/tests/Unit/Core/Addon/AddonInfoTest.php b/tests/Unit/Core/Addon/AddonInfoTest.php index a8e007b50a..a1887d5dfd 100644 --- a/tests/Unit/Core/Addon/AddonInfoTest.php +++ b/tests/Unit/Core/Addon/AddonInfoTest.php @@ -14,19 +14,65 @@ use PHPUnit\Framework\TestCase; class AddonInfoTest extends TestCase { + public function testFromStringCreatesObject(): void + { + $this->assertInstanceOf(AddonInfo::class, AddonInfo::fromString('addonId', '')); + } + + public static function getStringData(): array + { + return [ + 'minimal' => [ + 'test', + '', + ['id' => 'test'], + ], + 'complete' => [ + 'test', + << + * Maintainer: Robin + * Maintainer: Robin With Profile + * Status: beta + * Ignore: The "ignore" key is unsupported and will be ignored + */ + TEXT, + [ + 'id' => 'test', + 'name' => 'Test Addon', + 'description' => 'adds awesome features to friendica', + 'authors' => [ + ['name' => 'Sam'], + ['name' => 'Sam With Mail', 'link' => 'mail@example.org'], + ], + 'maintainers' => [ + ['name' => 'Robin'], + ['name' => 'Robin With Profile', 'link' => 'https://example.org/profile/robin'], + ], + 'version' => '100.4.50-beta.5', + 'status' => 'beta', + ], + ], + ]; + } + + /** + * @dataProvider getStringData + */ + public function testFromStringReturnsCorrectValues(string $addonId, string $raw, array $expected): void + { + $this->assertAddonInfoData($expected, AddonInfo::fromString($addonId, $raw)); + } + public function testFromArrayCreatesObject(): void { - $data = [ - 'id' => '', - 'name' => '', - 'description' => '', - 'authors' => [], - 'maintainers' => [], - 'version' => '', - 'status' => '', - ]; - - $this->assertInstanceOf(AddonInfo::class, AddonInfo::fromArray($data)); + $this->assertInstanceOf(AddonInfo::class, AddonInfo::fromArray([])); } public function testGetterReturningCorrectValues(): void @@ -41,15 +87,34 @@ class AddonInfoTest extends TestCase 'status' => 'In Development', ]; - $info = AddonInfo::fromArray($data); + $this->assertAddonInfoData($data, AddonInfo::fromArray($data)); + } - $this->assertSame($data['id'], $info->getId()); - $this->assertSame($data['name'], $info->getName()); - $this->assertSame($data['description'], $info->getDescription()); - $this->assertSame($data['description'], $info->getDescription()); - $this->assertSame($data['authors'], $info->getAuthors()); - $this->assertSame($data['maintainers'], $info->getMaintainers()); - $this->assertSame($data['version'], $info->getVersion()); - $this->assertSame($data['status'], $info->getStatus()); + private function assertAddonInfoData(array $expected, AddonInfo $info): void + { + $expected = array_merge( + [ + 'id' => '', + 'name' => '', + 'description' => '', + 'authors' => [], + 'maintainers' => [], + 'version' => '', + 'status' => '', + ], + $expected + ); + + $data = [ + 'id' => $info->getId(), + 'name' => $info->getName(), + 'description' => $info->getDescription(), + 'authors' => $info->getAuthors(), + 'maintainers' => $info->getMaintainers(), + 'version' => $info->getVersion(), + 'status' => $info->getStatus(), + ]; + + $this->assertSame($expected, $data); } }