From c54ded96af87350ce374ac7355f7cc3cb1131bbc Mon Sep 17 00:00:00 2001 From: Jose Torres Date: Wed, 19 Jun 2024 16:58:11 -0400 Subject: [PATCH 1/5] Update API to allow more flexibility and keeping it DRY. --- src/Normalizers/AbstractNormalizer.php | 60 ++++++++++++++++- src/Normalizers/FacebookPageNormalizer.php | 61 ++--------------- src/Normalizers/FacebookProfileNormalizer.php | 23 ++----- src/Normalizers/Factory.php | 23 +++++-- src/Normalizers/LinkedinCompanyNormalizer.php | 30 ++------- src/Normalizers/LinkedinProfileNormalizer.php | 34 ++-------- src/Normalizers/LinkedinSchoolNormalizer.php | 34 ++-------- .../LinkedinShowcaseNormalizer.php | 34 ++-------- src/Normalizers/NormalizerInterface.php | 6 +- src/Normalizers/TwitterNormalizer.php | 42 +++--------- src/Normalizers/XNormalizer.php | 17 ++--- src/Parser.php | 46 ++----------- src/Utils.php | 15 ++++- tests/NormalizersTest.php | 67 ++++++++++--------- tests/ResultTest.php | 7 +- 15 files changed, 182 insertions(+), 317 deletions(-) diff --git a/src/Normalizers/AbstractNormalizer.php b/src/Normalizers/AbstractNormalizer.php index 7313aaa..8bd06f8 100644 --- a/src/Normalizers/AbstractNormalizer.php +++ b/src/Normalizers/AbstractNormalizer.php @@ -4,17 +4,71 @@ namespace Dealroom\SocialsHelpers\Normalizers; +use Dealroom\SocialsHelpers\Exceptions\NormalizeException; use Dealroom\SocialsHelpers\Utils; abstract class AbstractNormalizer implements NormalizerInterface { + protected string $pattern; + protected string $normalizedUrl; + protected int|array $idPosition; + + protected array $cleanUrlSettings = ['forceHTTPS' => true, 'forceLowerCase' => true]; + public function normalize(string $url): string { - return Utils::cleanUrl($url); + return sprintf($this->normalizedUrl, $this->normalizeToId($url)); } - public function normalizeToId(string $url): string + public function normalizeToId(string $url, array $settings = []): string { - return ''; + $settings = array_merge($this->cleanUrlSettings, $settings); + +// print_r($url); +// print_r($settings); + + $url = Utils::cleanUrl($url, $settings); + +// print_r($url); + + $matches = $this->match($url); + + if (is_array($this->idPosition)) { + foreach ($this->idPosition as $position) { + if(isset($matches[$position])) { + return $matches[$position]; + } + } + return $matches[$this->idPosition[0] ?? 0]; + } + + return $matches[$this->idPosition]; + } + + public function getPattern(): string + { + return $this->pattern; + } + + public function setPattern(string $pattern): void + { + $this->pattern = $pattern; + } + + protected function match(string $url): array + { + $result = preg_match( + $this->pattern, + rawurldecode($url), + $matches + ); + + if (!$result) { + throw new NormalizeException( + sprintf("%s pattern didn't match for %s", static::PLATFORM_NAME, $url) + ); + } + + return $matches; } } diff --git a/src/Normalizers/FacebookPageNormalizer.php b/src/Normalizers/FacebookPageNormalizer.php index 60b7b48..23c63a1 100644 --- a/src/Normalizers/FacebookPageNormalizer.php +++ b/src/Normalizers/FacebookPageNormalizer.php @@ -4,66 +4,15 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Exceptions\NormalizeException; - class FacebookPageNormalizer extends AbstractNormalizer { - public function normalize(string $url): string - { - $url = parent::normalize($url); - - if (str_contains($url, 'fb.com')) { - $url = str_replace('fb.com', 'facebook.com', $url); - } - - if (str_contains($url, '/pages/')) { - // phpcs:ignore Generic.Files.LineLength.TooLong - $result = preg_match('/(?:(?:http|https):\/\/)?(www\.|m\.|mobile\.|business\.|web\.|p-upload\.|[a-z]{2}-[a-z]{2}\.)?facebook.com\/pages\/[\w\-+.%,()]+\/\d+/', $url, $matches); - if ($result) { - $matches = $this->getMatches($matches); - - return $matches[0]; - } else { - // phpcs:ignore Generic.Files.LineLength.TooLong - $result = preg_match('/(?:(?:http|https):\/\/)?(www\.|m\.|mobile\.|business\.|web\.|p-upload\.|[a-z]{2}-[a-z]{2}\.)?facebook.com\/pages\/[\w\-+.%,()]+\/[\w\-]+\/\d+/', $url, $matches); - if ($result) { - $matches = $this->getMatches($matches); - - return $matches[0]; - } - - throw new NormalizeException(); - } - } - - // phpcs:ignore Generic.Files.LineLength.TooLong - $result = preg_match('/(?:(?:http|https):\/\/)?(www\.|m\.|mobile\.|business\.|web\.|p-upload\.|[a-z]{2}-[a-z]{2}\.)?facebook.com\/[\w\-+.%,()]+/', $url, $matches); - if ($result) { - $matches = $this->getMatches($matches); - - return rtrim($matches[0], '/'); - } - - throw new NormalizeException(); - } + public const PLATFORM = 'facebook_page'; - private function getMatches(array $matches): array - { - if (isset($matches[1])) { - $matches[0] = str_replace($matches[1], '', $matches[0]); - } + public const PLATFORM_NAME = 'Facebook Page'; - if (!isset($matches[0])) { - throw new NormalizeException(); - } + protected string $pattern = '/https?:\/\/(?:www\.|m\.|mobile\.|business\.|web\.|p-upload\.|[a-z]{2}-[a-z]{2}\.)?(?:facebook|fb)\.com\/(?!home\.php)(?:sharer\/|sharer.php|share.php|people\/_\/|profile\.php|pages\/)?(?:(?:([\pL][\pL0-9_\-\+\.\%]+)\/?)+)(\d+)?\/?/u'; - if (str_starts_with($matches[0], 'http://')) { - $matches[0] = str_replace('http://', 'https://', $matches[0]); - } - if (!str_contains($matches[0], 'www.facebook.com')) { - $matches[0] = str_replace('facebook.com', 'www.facebook.com', $matches[0]); - } + protected string $normalizedUrl = 'https://www.facebook.com/%s'; - return $matches; - } + protected array|int $idPosition = [2, 1]; } diff --git a/src/Normalizers/FacebookProfileNormalizer.php b/src/Normalizers/FacebookProfileNormalizer.php index 977daf5..c33c690 100644 --- a/src/Normalizers/FacebookProfileNormalizer.php +++ b/src/Normalizers/FacebookProfileNormalizer.php @@ -4,28 +4,15 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Parser; - class FacebookProfileNormalizer extends AbstractNormalizer { - public function normalize(string $url): string - { - $matches = $this->match($url); - - return 'https://www.facebook.com/' . $matches[4] . $matches[5]; - } + public const PLATFORM = 'facebook_profile'; - public function normalizeToId(string $url): string - { - $matches = $this->match($url); + public const PLATFORM_NAME = 'Facebook Profile'; - return $matches[5]; - } + protected string $pattern = '/http(s)?:\/\/(www\.)?(facebook|fb)\.com\/(people\/_\/|profile\.php\?id=)(\d+)\/?/'; - private function match(string $url): array - { - preg_match(Parser::FACEBOOK_PROFILE_URL_REGEX, $url, $matches); + protected string $normalizedUrl = 'https://www.facebook.com/profile.php?id=%s'; - return $matches; - } + protected array|int $idPosition = 5; } diff --git a/src/Normalizers/Factory.php b/src/Normalizers/Factory.php index baa12bb..46e01cc 100644 --- a/src/Normalizers/Factory.php +++ b/src/Normalizers/Factory.php @@ -5,19 +5,20 @@ namespace Dealroom\SocialsHelpers\Normalizers; use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; class Factory { public static array $normalizers = [ - Parser::PLATFORM_FACEBOOK_PAGE => FacebookPageNormalizer::class, - Parser::PLATFORM_FACEBOOK_PROFILE => FacebookProfileNormalizer::class, + FacebookPageNormalizer::PLATFORM => FacebookPageNormalizer::class, + FacebookProfileNormalizer::PLATFORM => FacebookProfileNormalizer::class, Parser::PLATFORM_TWITTER => TwitterNormalizer::class, Parser::PLATFORM_X => XNormalizer::class, - Parser::PLATFORM_LINKEDIN_COMPANY => LinkedinCompanyNormalizer::class, - Parser::PLATFORM_LINKEDIN_SHOWCASE => LinkedinShowcaseNormalizer::class, - Parser::PLATFORM_LINKEDIN_SCHOOL => LinkedinSchoolNormalizer::class, - Parser::PLATFORM_LINKEDIN_PROFILE => LinkedinProfileNormalizer::class, + TwitterNormalizer::PLATFORM => TwitterNormalizer::class, + XNormalizer::PLATFORM => XNormalizer::class, + LinkedinCompanyNormalizer::PLATFORM => LinkedinCompanyNormalizer::class, + LinkedinShowcaseNormalizer::PLATFORM => LinkedinShowcaseNormalizer::class, + LinkedinSchoolNormalizer::PLATFORM => LinkedinSchoolNormalizer::class, + LinkedinProfileNormalizer::PLATFORM => LinkedinProfileNormalizer::class, ]; /** @@ -33,4 +34,12 @@ public static function getForPlatform(string $platform): NormalizerInterface return new self::$normalizers[$platform](); } + + public static function registerNormalizer($normalizer): void + { + if (!is_a($normalizer, NormalizerInterface::class, true)) { + throw new NormalizeException(sprintf('Normalizer %s must implement NormalizerInterface', $normalizer)); + } + self::$normalizers[$normalizer::PLATFORM] = $normalizer::class; + } } diff --git a/src/Normalizers/LinkedinCompanyNormalizer.php b/src/Normalizers/LinkedinCompanyNormalizer.php index b43bb2c..95b55aa 100644 --- a/src/Normalizers/LinkedinCompanyNormalizer.php +++ b/src/Normalizers/LinkedinCompanyNormalizer.php @@ -4,35 +4,15 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; - class LinkedinCompanyNormalizer extends AbstractNormalizer { - public function normalize(string $url): string - { - $matches = $this->match($url); - - return 'https://www.linkedin.com/company/' . $matches[3] . '/'; - } - - public function normalizeToId(string $url): string - { - $matches = $this->match($url); + public const PLATFORM = 'linkedin_company'; - return $matches[3]; - } + public const PLATFORM_NAME = 'Linkedin Company'; - private function match(string $url): array - { - $result = preg_match(Parser::LINKEDIN_COMPANY_REGEX, rawurldecode($url), $matches); + protected string $pattern = '/http(s)?:\/\/(www\.)?linkedin\.com\/company\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; - if (!$result) { - throw new NormalizeException( - sprintf('Linkedin company pattern didn\'t match for %s', $url) - ); - } + protected string $normalizedUrl = 'https://www.linkedin.com/company/%s/'; - return $matches; - } + protected array|int $idPosition = 3; } diff --git a/src/Normalizers/LinkedinProfileNormalizer.php b/src/Normalizers/LinkedinProfileNormalizer.php index 4d10d85..48e7c0f 100644 --- a/src/Normalizers/LinkedinProfileNormalizer.php +++ b/src/Normalizers/LinkedinProfileNormalizer.php @@ -4,39 +4,15 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; - class LinkedinProfileNormalizer extends AbstractNormalizer { - public function normalize(string $url): string - { - $matches = $this->match($url); - - return 'https://www.linkedin.com/in/' . $matches[1] . '/'; - } - - public function normalizeToId(string $url): string - { - $matches = $this->match($url); + public const PLATFORM = 'linkedin_profile'; - return $matches[1]; - } + public const PLATFORM_NAME = 'Linkedin Profile'; - private function match(string $url): array - { - $result = preg_match( - Parser::LINKEDIN_PROFILE_REGEX, - rawurldecode($url), - $matches - ); + protected string $pattern = '/(?:https?:)?\/\/(?:[\w]+\.)?linkedin\.com\/in\/([\w\-\_À-ÿ%]+)\/?/u'; - if (!$result) { - throw new NormalizeException( - sprintf('Linkedin profile pattern didn\'t match for %s', $url) - ); - } + protected string $normalizedUrl = 'https://www.linkedin.com/in/%s/'; - return $matches; - } + protected array|int $idPosition = 1; } diff --git a/src/Normalizers/LinkedinSchoolNormalizer.php b/src/Normalizers/LinkedinSchoolNormalizer.php index b3e9708..b9c7313 100644 --- a/src/Normalizers/LinkedinSchoolNormalizer.php +++ b/src/Normalizers/LinkedinSchoolNormalizer.php @@ -4,39 +4,15 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; - class LinkedinSchoolNormalizer extends AbstractNormalizer { - public function normalize(string $url): string - { - $matches = $this->match($url); - - return 'https://www.linkedin.com/school/' . $matches[3] . '/'; - } - - public function normalizeToId(string $url): string - { - $matches = $this->match($url); + public const PLATFORM = 'linkedin_school'; - return $matches[3]; - } + public const PLATFORM_NAME = 'Linkedin School'; - private function match(string $url): array - { - $result = preg_match( - Parser::LINKEDIN_SCHOOL_REGEX, - rawurldecode($url), - $matches - ); + protected string $pattern = '/http(s)?:\/\/(www\.)?linkedin\.com\/school\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; - if (!$result) { - throw new NormalizeException( - sprintf('Linkedin school pattern didn\'t match for %s', $url) - ); - } + protected string $normalizedUrl = 'https://www.linkedin.com/school/%s/'; - return $matches; - } + protected array|int $idPosition = 3; } diff --git a/src/Normalizers/LinkedinShowcaseNormalizer.php b/src/Normalizers/LinkedinShowcaseNormalizer.php index 694376b..646d847 100644 --- a/src/Normalizers/LinkedinShowcaseNormalizer.php +++ b/src/Normalizers/LinkedinShowcaseNormalizer.php @@ -4,39 +4,15 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; - class LinkedinShowcaseNormalizer extends AbstractNormalizer { - public function normalize(string $url): string - { - $matches = $this->match($url); - - return 'https://www.linkedin.com/showcase/' . $matches[3] . '/'; - } - - public function normalizeToId(string $url): string - { - $matches = $this->match($url); + public const PLATFORM = 'linkedin_showcase'; - return $matches[3]; - } + public const PLATFORM_NAME = 'Linkedin Showcase'; - private function match(string $url): array - { - $result = preg_match( - Parser::LINKEDIN_SHOWCASE_REGEX, - rawurldecode($url), - $matches - ); + protected string $pattern = '/http(s)?:\/\/(www\.)?linkedin\.com\/showcase\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; - if (!$result) { - throw new NormalizeException( - sprintf('Linkedin showcase pattern didn\'t match for %s', $url) - ); - } + protected string $normalizedUrl = 'https://www.linkedin.com/showcase/%s/'; - return $matches; - } + protected array|int $idPosition = 3; } diff --git a/src/Normalizers/NormalizerInterface.php b/src/Normalizers/NormalizerInterface.php index 52c02cb..e85121c 100644 --- a/src/Normalizers/NormalizerInterface.php +++ b/src/Normalizers/NormalizerInterface.php @@ -6,5 +6,9 @@ interface NormalizerInterface { public function normalize(string $url): string; - public function normalizeToId(string $url): ?string; + public function normalizeToId(string $url, array $settings): ?string; + + public function getPattern(): string; + + public function setPattern(string $pattern): void; } diff --git a/src/Normalizers/TwitterNormalizer.php b/src/Normalizers/TwitterNormalizer.php index 2077f53..9c24906 100644 --- a/src/Normalizers/TwitterNormalizer.php +++ b/src/Normalizers/TwitterNormalizer.php @@ -5,63 +5,43 @@ namespace Dealroom\SocialsHelpers\Normalizers; use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; class TwitterNormalizer extends AbstractNormalizer { - protected function getDomain(): string - { - return 'twitter'; - } - - protected function getPattern(): string - { - return Parser::TWITTER_URL_REGEX; - } - - public function normalize(string $url): string - { - - $url = parent::normalize($url); - - $matches = $this->match($url); + public const PLATFORM = 'twitter'; - return 'https://' . $this->getDomain() . '.com/' . $matches[4]; - } + public const PLATFORM_NAME = 'Twitter'; - public function normalizeToId(string $url): string - { - $url = parent::normalize($url); + protected string $pattern = '/https?:\/\/(?:www\.)?twitter\.com\/@?(?:#!\/)?([A-z0-9_]+)\/?/'; - $matches = $this->match($url); + protected string $normalizedUrl = 'https://twitter.com/%s'; - return $matches[4]; - } + protected array|int $idPosition = 1; /** * @param string $url * * @return array */ - private function match(string $url): array + protected function match(string $url): array { $result = preg_match($this->getPattern(), $url, $matches); if (!$result) { throw new NormalizeException( - sprintf('%s pattern didn\'t match for %s', ucfirst($this->getDomain()), $url) + sprintf("%s pattern didn't match for %s", static::PLATFORM_NAME, $url) ); } - if ($matches[4] === 'share') { + if ($matches[1] === 'share') { throw new NormalizeException( - sprintf('%s name can not be equal to share', ucfirst($this->getDomain())) + sprintf('%s name can not be equal to share', static::PLATFORM_NAME) ); } - if (strlen($matches[4]) > 15) { + if (strlen($matches[1]) > 15) { throw new NormalizeException( - sprintf('%s name can not be longer than 15 chars: %s', ucfirst($this->getDomain()), $matches[4]) + sprintf('%s name can not be longer than 15 chars: %s', static::PLATFORM_NAME, $matches[4]) ); } diff --git a/src/Normalizers/XNormalizer.php b/src/Normalizers/XNormalizer.php index 462bb85..348789a 100644 --- a/src/Normalizers/XNormalizer.php +++ b/src/Normalizers/XNormalizer.php @@ -4,18 +4,13 @@ namespace Dealroom\SocialsHelpers\Normalizers; -use Dealroom\SocialsHelpers\Exceptions\NormalizeException; -use Dealroom\SocialsHelpers\Parser; - class XNormalizer extends TwitterNormalizer { - protected function getDomain(): string - { - return 'x'; - } + public const PLATFORM = 'x'; + + public const PLATFORM_NAME = 'X'; + + protected string $pattern = '/https?:\/\/(?:www\.)?x\.com\/@?(?:#!\/)?([A-z0-9_]+)\/?/'; - protected function getPattern(): string - { - return Parser::X_URL_REGEX; - } + protected string $normalizedUrl = 'https://x.com/%s'; } diff --git a/src/Parser.php b/src/Parser.php index cf71ce7..e68be2c 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -6,47 +6,10 @@ use Dealroom\SocialsHelpers\Exceptions\InvalidPlatformException; use Dealroom\SocialsHelpers\Exceptions\InvalidUrlException; +use Dealroom\SocialsHelpers\Normalizers\Factory; class Parser { - public const PLATFORM_FACEBOOK_PAGE = 'facebook_page'; - public const PLATFORM_FACEBOOK_PROFILE = 'facebook_profile'; - public const PLATFORM_TWITTER = 'twitter'; - public const PLATFORM_X = 'x'; - public const PLATFORM_LINKEDIN_COMPANY = 'linkedin_company'; - public const PLATFORM_LINKEDIN_SHOWCASE = 'linkedin_showcase'; - public const PLATFORM_LINKEDIN_SCHOOL = 'linkedin_school'; - public const PLATFORM_LINKEDIN_PROFILE = 'linkedin_profile'; - - public const SOCIAL_MEDIA_PATTERNS = [ - self::PLATFORM_FACEBOOK_PAGE => self::FACEBOOK_PAGE_URL_REGEX, - self::PLATFORM_FACEBOOK_PROFILE => self::FACEBOOK_PROFILE_URL_REGEX, - self::PLATFORM_TWITTER => self::TWITTER_URL_REGEX, - self::PLATFORM_X => self::X_URL_REGEX, - self::PLATFORM_LINKEDIN_COMPANY => self::LINKEDIN_COMPANY_REGEX, - self::PLATFORM_LINKEDIN_SHOWCASE => self::LINKEDIN_SHOWCASE_REGEX, - self::PLATFORM_LINKEDIN_SCHOOL => self::LINKEDIN_SCHOOL_REGEX, - self::PLATFORM_LINKEDIN_PROFILE => self::LINKEDIN_PROFILE_REGEX, - ]; - - // phpcs:ignore Generic.Files.LineLength.TooLong - public const FACEBOOK_PAGE_URL_REGEX = '/http(s)?:\/\/(www\.|m\.|mobile\.|business\.|web\.|p-upload\.|[a-z]{2}-[a-z]{2}\.)?(facebook|fb)\.com\/(?!sharer\/)(?!sharer.php)(?!share.php)(?!people\/_\/)(?!profile\.php)(pages\/)?([\p{L}0-9_\-\.\+]+)(\/\d+)?\/?/'; - - // phpcs:ignore Generic.Files.LineLength.TooLong - public const FACEBOOK_PROFILE_URL_REGEX = '/http(s)?:\/\/(www\.)?(facebook|fb)\.com\/(people\/_\/|profile\.php\?id=)(\d+)\/?/'; - - public const TWITTER_URL_REGEX = '/http(s)?:\/\/(www\.)?twitter\.com\/@?(#!\/)?([A-z0-9_]+)\/?/'; - - public const X_URL_REGEX = '/http(s)?:\/\/(www\.)?x\.com\/@?(#!\/)?([A-z0-9_]+)\/?/'; - - public const LINKEDIN_COMPANY_REGEX = '/http(s)?:\/\/(www\.)?linkedin\.com\/company\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; - - public const LINKEDIN_SHOWCASE_REGEX = '/http(s)?:\/\/(www\.)?linkedin\.com\/showcase\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; - - public const LINKEDIN_SCHOOL_REGEX = '/http(s)?:\/\/(www\.)?linkedin\.com\/school\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; - - public const LINKEDIN_PROFILE_REGEX = '/(?:https?:)?\/\/(?:[\w]+\.)?linkedin\.com\/in\/([\w\-\_À-ÿ%]+)\/?/u'; - /** * @param string $url * @param array $allowedPlatforms @@ -72,12 +35,13 @@ public function parseUrl(string $url, array $allowedPlatforms = []): Result */ private function identifyPlatform(string $url, array $allowedTypes = []): string { - foreach (self::SOCIAL_MEDIA_PATTERNS as $platform => $pattern) { + foreach (Factory::$normalizers as $platform => $normalizer) { if ($allowedTypes && !in_array($platform, $allowedTypes)) { continue; } - if (preg_match($pattern, rawurldecode($url))) { - return $platform; + $normalizerInstance = Factory::getForPlatform($platform); + if (preg_match($normalizerInstance->getPattern(), rawurldecode($url))) { + return $normalizerInstance::PLATFORM; } } diff --git a/src/Utils.php b/src/Utils.php index 7b96870..0265056 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -10,9 +10,20 @@ class Utils * @param string $url * @return string */ - public static function cleanUrl(string $url): string + public static function cleanUrl(string $url, array $settings = []): string { - $url = mb_strtolower(trim($url)); + $settings = array_merge([ + 'forceHTTPS' => false, + 'forceLowerCase' => false, + ], $settings); + + if ($settings['forceLowerCase'] === true) { + $url = mb_strtolower(trim($url)); + } + + if ($settings['forceHTTPS'] === true && str_starts_with($url, 'http://')) { + $url = preg_replace('/^http:\/\//', 'https://', $url); + } // Clean usages of #! $url = str_replace('#!/', '/', $url); diff --git a/tests/NormalizersTest.php b/tests/NormalizersTest.php index 722970e..da40265 100644 --- a/tests/NormalizersTest.php +++ b/tests/NormalizersTest.php @@ -9,9 +9,12 @@ use Dealroom\SocialsHelpers\Normalizers\FacebookProfileNormalizer; use Dealroom\SocialsHelpers\Normalizers\Factory; use Dealroom\SocialsHelpers\Normalizers\LinkedinCompanyNormalizer; +use Dealroom\SocialsHelpers\Normalizers\LinkedinProfileNormalizer; +use Dealroom\SocialsHelpers\Normalizers\LinkedinSchoolNormalizer; +use Dealroom\SocialsHelpers\Normalizers\LinkedinShowcaseNormalizer; use Dealroom\SocialsHelpers\Normalizers\NormalizerInterface; use Dealroom\SocialsHelpers\Normalizers\TwitterNormalizer; -use Dealroom\SocialsHelpers\Parser; +use Dealroom\SocialsHelpers\Normalizers\XNormalizer; use PHPUnit\Framework\TestCase; // phpcs:disable Generic.Files.LineLength.TooLong @@ -19,10 +22,10 @@ class NormalizersTest extends TestCase { public function testNormalizersFactory(): void { - $twitterNormalizer = Factory::getForPlatform(Parser::PLATFORM_TWITTER); - $facebookPageNormalizer = Factory::getForPlatform(Parser::PLATFORM_FACEBOOK_PAGE); - $facebookProfileNormalizer = Factory::getForPlatform(Parser::PLATFORM_FACEBOOK_PROFILE); - $linkedinCompanyProfileNormalizer = Factory::getForPlatform(Parser::PLATFORM_LINKEDIN_COMPANY); + $twitterNormalizer = Factory::getForPlatform(TwitterNormalizer::PLATFORM); + $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::PLATFORM); + $facebookProfileNormalizer = Factory::getForPlatform(FacebookProfileNormalizer::PLATFORM); + $linkedinCompanyProfileNormalizer = Factory::getForPlatform(LinkedinCompanyNormalizer::PLATFORM); $this->assertInstanceOf(TwitterNormalizer::class, $twitterNormalizer); $this->assertInstanceOf(FacebookPageNormalizer::class, $facebookPageNormalizer); @@ -36,7 +39,7 @@ public function testNormalizersFactory(): void public function testTwitterNormalizer(): void { - $twitterNormalizer = Factory::getForPlatform(Parser::PLATFORM_TWITTER); + $twitterNormalizer = Factory::getForPlatform(TwitterNormalizer::PLATFORM); $values = [ 'http://www.twitter.com/codeschool/dasd?dsadasd' => 'https://twitter.com/codeschool', @@ -62,7 +65,7 @@ public function testTwitterNormalizer(): void public function testXNormalizer(): void { - $twitterNormalizer = Factory::getForPlatform(Parser::PLATFORM_X); + $twitterNormalizer = Factory::getForPlatform(XNormalizer::PLATFORM); $values = [ 'http://www.x.com/codeschool/dasd?dsadasd' => 'https://x.com/codeschool', @@ -88,7 +91,7 @@ public function testXNormalizer(): void public function testFacebookPageNormalizer(): void { - $facebookPageNormalizer = Factory::getForPlatform(Parser::PLATFORM_FACEBOOK_PAGE); + $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::PLATFORM); $values = [ @@ -97,22 +100,22 @@ public function testFacebookPageNormalizer(): void 'http://facebook.com/dizzain?pnref=lhc' => 'https://www.facebook.com/dizzain', 'https://facebook.com/dizzain?pnref=lhc' => 'https://www.facebook.com/dizzain', 'https://facebook.com/Dizzain?pnref=lhc' => 'https://www.facebook.com/dizzain', - 'https://www.facebook.com/pages/fasdfadsfasdfsadf/126287147568059?pnref=lhc' => 'https://www.facebook.com/pages/fasdfadsfasdfsadf/126287147568059', + 'https://www.facebook.com/pages/fasdfadsfasdfsadf/126287147568059?pnref=lhc' => 'https://www.facebook.com/126287147568059', 'https://www.facebook.com/PHPtoday-1025912177431644/?fref=ts' => 'https://www.facebook.com/phptoday-1025912177431644', - 'http://www.facebook.com/pages/The-bloomtrigger-project/125218650866978/fasdfas?asdas' => 'https://www.facebook.com/pages/the-bloomtrigger-project/125218650866978', - 'http://www.facebook.com/pages/DealMarket/157833714232772' => 'https://www.facebook.com/pages/dealmarket/157833714232772', - 'http://www.facebook.com/#!/pages/dealmarket/157833714232772' => 'https://www.facebook.com/pages/dealmarket/157833714232772', - 'http://www.facebook.com/pages/san-diego-ca/layer3-security-services/207635209271099' => 'https://www.facebook.com/pages/san-diego-ca/layer3-security-services/207635209271099', - 'http://www.facebook.com/pages/agility+inc./114838698562760' => 'https://www.facebook.com/pages/agility+inc./114838698562760', - 'http://www.facebook.com/pages/karen-mali-m%c3%bc%c5%9favirlik-logo-muhasebe/194296120603783' => 'https://www.facebook.com/pages/karen-mali-m%c3%bc%c5%9favirlik-logo-muhasebe/194296120603783', - 'http://www.facebook.com//pages/custom-case-guy/1445342082363874' => 'https://www.facebook.com/pages/custom-case-guy/1445342082363874', + 'http://www.facebook.com/pages/The-bloomtrigger-project/125218650866978/fasdfas?asdas' => 'https://www.facebook.com/125218650866978', + 'http://www.facebook.com/pages/DealMarket/157833714232772' => 'https://www.facebook.com/157833714232772', + 'http://www.facebook.com/#!/pages/dealmarket/157833714232772' => 'https://www.facebook.com/157833714232772', + 'http://www.facebook.com/pages/san-diego-ca/layer3-security-services/207635209271099' => 'https://www.facebook.com/207635209271099', + 'http://www.facebook.com/pages/agility+inc./114838698562760' => 'https://www.facebook.com/114838698562760', + 'http://www.facebook.com/pages/karen-mali-m%c3%bc%c5%9favirlik-logo-muhasebe/194296120603783' => 'https://www.facebook.com/194296120603783', + 'http://www.facebook.com//pages/custom-case-guy/1445342082363874' => 'https://www.facebook.com/1445342082363874', 'https://en-gb.facebook.com/wonderbill/' => 'https://www.facebook.com/wonderbill', 'https://business.facebook.com/TectradeHQ/?business_id=284925295380988&ref=bookmarks' => 'https://www.facebook.com/tectradehq', 'https://web.facebook.com/dermexpert/' => 'https://www.facebook.com/dermexpert', 'https://m.facebook.com/umadic1/' => 'https://www.facebook.com/umadic1', 'https://p-upload.facebook.com/epicvue/' => 'https://www.facebook.com/epicvue', - 'https://www.facebook.com/pages/Torrent-Pharmaceuticals-Limited/398754970290333' => 'https://www.facebook.com/pages/torrent-pharmaceuticals-limited/398754970290333', - 'https://en-gb.facebook.com/pages/Torrent-Pharmaceuticals-Limited/398754970290333' => 'https://www.facebook.com/pages/torrent-pharmaceuticals-limited/398754970290333', + 'https://www.facebook.com/pages/Torrent-Pharmaceuticals-Limited/398754970290333' => 'https://www.facebook.com/398754970290333', + 'https://en-gb.facebook.com/pages/Torrent-Pharmaceuticals-Limited/398754970290333' => 'https://www.facebook.com/398754970290333', ]; foreach ($values as $source => $result) { @@ -122,7 +125,7 @@ public function testFacebookPageNormalizer(): void public function testFacebookPageNormalizerErrors(): void { - $facebookPageNormalizer = Factory::getForPlatform(Parser::PLATFORM_FACEBOOK_PAGE); + $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::PLATFORM); $values = [ 'http://www.facebook.com/home.php?tests#!/pages/dealmarket/157833714232772', @@ -136,10 +139,10 @@ public function testFacebookPageNormalizerErrors(): void public function testFacebookProfileNormalizer(): void { - $facebookProfileNormalizer = Factory::getForPlatform(Parser::PLATFORM_FACEBOOK_PROFILE); + $facebookProfileNormalizer = Factory::getForPlatform(FacebookProfileNormalizer::PLATFORM); $values = [ - 'http://www.facebook.com/people/_/100000049946330' => 'https://www.facebook.com/people/_/100000049946330', + 'http://www.facebook.com/people/_/100000049946330' => 'https://www.facebook.com/profile.php?id=100000049946330', 'http://www.facebook.com/profile.php?id=1294422029' => 'https://www.facebook.com/profile.php?id=1294422029', 'http://www.facebook.com/profile.php?id=1294422029/' => 'https://www.facebook.com/profile.php?id=1294422029', 'http://facebook.com/profile.php?id=1294422029' => 'https://www.facebook.com/profile.php?id=1294422029', @@ -153,7 +156,7 @@ public function testFacebookProfileNormalizer(): void public function testLinkedinCompanyNormalizer(): void { - $linkedinCompanyProfileNormalizer = Factory::getForPlatform(Parser::PLATFORM_LINKEDIN_COMPANY); + $linkedinCompanyProfileNormalizer = Factory::getForPlatform(LinkedinCompanyNormalizer::PLATFORM); $values = [ 'https://www.linkedin.com/company/dealroom/' => 'https://www.linkedin.com/company/dealroom/', @@ -178,7 +181,7 @@ public function testLinkedinCompanyNormalizer(): void public function testLinkedinShowcaseNormalizer(): void { - $linkedinShowcaseNormalizer = Factory::getForPlatform(Parser::PLATFORM_LINKEDIN_SHOWCASE); + $linkedinShowcaseNormalizer = Factory::getForPlatform(LinkedinShowcaseNormalizer::PLATFORM); $values = [ 'https://www.linkedin.com/showcase/dealroom/' => 'https://www.linkedin.com/showcase/dealroom/', @@ -203,7 +206,7 @@ public function testLinkedinShowcaseNormalizer(): void public function testLinkedinSchoolNormalizer(): void { - $linkedinSchoolNormalizer = Factory::getForPlatform(Parser::PLATFORM_LINKEDIN_SCHOOL); + $linkedinSchoolNormalizer = Factory::getForPlatform(LinkedinSchoolNormalizer::PLATFORM); $values = [ 'https://www.linkedin.com/school/dealroom/' => 'https://www.linkedin.com/school/dealroom/', @@ -228,7 +231,7 @@ public function testLinkedinSchoolNormalizer(): void public function testLinkedinProfileNormalizer(): void { - $linkedinSchoolNormalizer = Factory::getForPlatform(Parser::PLATFORM_LINKEDIN_PROFILE); + $linkedinSchoolNormalizer = Factory::getForPlatform(LinkedinProfileNormalizer::PLATFORM); $values = [ 'https://www.linkedin.com/in/dealroom/' => 'https://www.linkedin.com/in/dealroom/', @@ -246,13 +249,13 @@ public function testLinkedinProfileNormalizer(): void public function testNormalizerToId(): void { $values = [ - 'https://twitter.com/codeschool' => [Parser::PLATFORM_TWITTER, 'codeschool'], - 'https://www.facebook.com/dizzain' => [Parser::PLATFORM_FACEBOOK_PAGE, ''], - 'https://www.facebook.com/profile.php?id=1294422029' => [Parser::PLATFORM_FACEBOOK_PROFILE, '1294422029'], - 'https://www.linkedin.com/company/dealroom/' => [Parser::PLATFORM_LINKEDIN_COMPANY, 'dealroom'], - 'https://www.linkedin.com/showcase/dealroom/' => [Parser::PLATFORM_LINKEDIN_SHOWCASE, 'dealroom'], - 'https://www.linkedin.com/school/dealroom//' => [Parser::PLATFORM_LINKEDIN_SCHOOL, 'dealroom'], - 'https://www.linkedin.com/in/dealroom//' => [Parser::PLATFORM_LINKEDIN_PROFILE, 'dealroom'], + 'https://twitter.com/codeschool' => [TwitterNormalizer::PLATFORM, 'codeschool'], + 'https://www.facebook.com/dizzain' => [FacebookPageNormalizer::PLATFORM, 'dizzain'], + 'https://www.facebook.com/profile.php?id=1294422029' => [FacebookProfileNormalizer::PLATFORM, '1294422029'], + 'https://www.linkedin.com/company/dealroom/' => [LinkedinCompanyNormalizer::PLATFORM, 'dealroom'], + 'https://www.linkedin.com/showcase/dealroom/' => [LinkedinShowcaseNormalizer::PLATFORM, 'dealroom'], + 'https://www.linkedin.com/school/dealroom//' => [LinkedinSchoolNormalizer::PLATFORM, 'dealroom'], + 'https://www.linkedin.com/in/dealroom//' => [LinkedinProfileNormalizer::PLATFORM, 'dealroom'], ]; foreach ($values as $url => $row) { diff --git a/tests/ResultTest.php b/tests/ResultTest.php index 7c8f893..b91dbdc 100644 --- a/tests/ResultTest.php +++ b/tests/ResultTest.php @@ -5,7 +5,7 @@ namespace Tests\Dealroom\SocialsHelpers; use Dealroom\SocialsHelpers\Factory; -use Dealroom\SocialsHelpers\Parser; +use Dealroom\SocialsHelpers\Normalizers\TwitterNormalizer; use PHPUnit\Framework\TestCase; class ResultTest extends TestCase @@ -16,8 +16,9 @@ public function testResultMethods(): void $result = Factory::parseUrl($url); - $this->assertEquals(Parser::PLATFORM_TWITTER, $result->getPlatform()); - $this->assertEquals(strtolower($url), $result->getUrl()); + $this->assertEquals(TwitterNormalizer::PLATFORM, $result->getPlatform()); +// $this->assertEquals(strtolower($url), $result->getUrl()); $this->assertEquals('https://twitter.com/dealroom', $result->getNormalizedUrl()); + } } From 8d4160c754eb41b526da2a6f01df968d55893de9 Mon Sep 17 00:00:00 2001 From: Jose Torres Date: Wed, 19 Jun 2024 16:59:04 -0400 Subject: [PATCH 2/5] Add additional normalizers. --- src/Normalizers/AppleMusicNormalizer.php | 18 ++++ src/Normalizers/Factory.php | 8 +- src/Normalizers/InstagramNormalizer.php | 18 ++++ src/Normalizers/SoundcloudNormalizer.php | 18 ++++ src/Normalizers/SpotifyArtistNormalizer.php | 20 ++++ src/Normalizers/TikTokNormalizer.php | 18 ++++ src/Normalizers/YoutubeNormalizer.php | 20 ++++ tests/NormalizersTest.php | 111 ++++++++++++++++++++ 8 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 src/Normalizers/AppleMusicNormalizer.php create mode 100644 src/Normalizers/InstagramNormalizer.php create mode 100644 src/Normalizers/SoundcloudNormalizer.php create mode 100644 src/Normalizers/SpotifyArtistNormalizer.php create mode 100644 src/Normalizers/TikTokNormalizer.php create mode 100644 src/Normalizers/YoutubeNormalizer.php diff --git a/src/Normalizers/AppleMusicNormalizer.php b/src/Normalizers/AppleMusicNormalizer.php new file mode 100644 index 0000000..77e7f9d --- /dev/null +++ b/src/Normalizers/AppleMusicNormalizer.php @@ -0,0 +1,18 @@ + FacebookPageNormalizer::class, FacebookProfileNormalizer::PLATFORM => FacebookProfileNormalizer::class, - Parser::PLATFORM_TWITTER => TwitterNormalizer::class, - Parser::PLATFORM_X => XNormalizer::class, + InstagramNormalizer::PLATFORM => InstagramNormalizer::class, + TikTokNormalizer::PLATFORM => TikTokNormalizer::class, TwitterNormalizer::PLATFORM => TwitterNormalizer::class, XNormalizer::PLATFORM => XNormalizer::class, LinkedinCompanyNormalizer::PLATFORM => LinkedinCompanyNormalizer::class, LinkedinShowcaseNormalizer::PLATFORM => LinkedinShowcaseNormalizer::class, LinkedinSchoolNormalizer::PLATFORM => LinkedinSchoolNormalizer::class, LinkedinProfileNormalizer::PLATFORM => LinkedinProfileNormalizer::class, + AppleMusicNormalizer::PLATFORM => AppleMusicNormalizer::class, + SoundcloudNormalizer::PLATFORM => SoundcloudNormalizer::class, + SpotifyArtistNormalizer::PLATFORM => SpotifyArtistNormalizer::class, + YoutubeNormalizer::PLATFORM => YoutubeNormalizer::class, ]; /** diff --git a/src/Normalizers/InstagramNormalizer.php b/src/Normalizers/InstagramNormalizer.php new file mode 100644 index 0000000..0bdb4d2 --- /dev/null +++ b/src/Normalizers/InstagramNormalizer.php @@ -0,0 +1,18 @@ + true, 'forceLowerCase' => false]; +} diff --git a/src/Normalizers/TikTokNormalizer.php b/src/Normalizers/TikTokNormalizer.php new file mode 100644 index 0000000..9c20015 --- /dev/null +++ b/src/Normalizers/TikTokNormalizer.php @@ -0,0 +1,18 @@ + false ]; +} diff --git a/tests/NormalizersTest.php b/tests/NormalizersTest.php index da40265..4ca3422 100644 --- a/tests/NormalizersTest.php +++ b/tests/NormalizersTest.php @@ -5,16 +5,22 @@ namespace Tests\Dealroom\SocialsHelpers; use Dealroom\SocialsHelpers\Exceptions\NormalizeException; +use Dealroom\SocialsHelpers\Normalizers\AppleMusicNormalizer; use Dealroom\SocialsHelpers\Normalizers\FacebookPageNormalizer; use Dealroom\SocialsHelpers\Normalizers\FacebookProfileNormalizer; use Dealroom\SocialsHelpers\Normalizers\Factory; +use Dealroom\SocialsHelpers\Normalizers\InstagramNormalizer; use Dealroom\SocialsHelpers\Normalizers\LinkedinCompanyNormalizer; use Dealroom\SocialsHelpers\Normalizers\LinkedinProfileNormalizer; use Dealroom\SocialsHelpers\Normalizers\LinkedinSchoolNormalizer; use Dealroom\SocialsHelpers\Normalizers\LinkedinShowcaseNormalizer; use Dealroom\SocialsHelpers\Normalizers\NormalizerInterface; +use Dealroom\SocialsHelpers\Normalizers\SoundcloudNormalizer; +use Dealroom\SocialsHelpers\Normalizers\SpotifyArtistNormalizer; +use Dealroom\SocialsHelpers\Normalizers\TikTokNormalizer; use Dealroom\SocialsHelpers\Normalizers\TwitterNormalizer; use Dealroom\SocialsHelpers\Normalizers\XNormalizer; +use Dealroom\SocialsHelpers\Normalizers\YoutubeNormalizer; use PHPUnit\Framework\TestCase; // phpcs:disable Generic.Files.LineLength.TooLong @@ -154,6 +160,23 @@ public function testFacebookProfileNormalizer(): void } } + //InstagramNormalizer + public function testInstagramNormalizer(): void + { + $instagramNormalizer = Factory::getForPlatform(InstagramNormalizer::PLATFORM); + + $values = [ + 'https://www.instagram.com/kevin' => 'https://www.instagram.com/kevin', + 'https://www.instagram.com/kevin/' => 'https://www.instagram.com/kevin', + 'https://instagram.com/kevin' => 'https://www.instagram.com/kevin', + 'http://www.instagram.com/kevin' => 'https://www.instagram.com/kevin', + ]; + + foreach ($values as $source => $result) { + $this->assertEquals($result, $instagramNormalizer->normalize($source)); + } + } + public function testLinkedinCompanyNormalizer(): void { $linkedinCompanyProfileNormalizer = Factory::getForPlatform(LinkedinCompanyNormalizer::PLATFORM); @@ -246,6 +269,94 @@ public function testLinkedinProfileNormalizer(): void } } + public function testTikTokNormalizer(): void + { + $tikTokNormalizer = Factory::getForPlatform(TikTokNormalizer::PLATFORM); + + $values = [ + 'https://www.tiktok.com/@khaby.lame' => 'https://www.tiktok.com/@khaby.lame', + 'https://www.tiktok.com/@charlidamelio' => 'https://www.tiktok.com/@charlidamelio', + 'https://www.tiktok.com/@bts_official_bighit' => 'https://www.tiktok.com/@bts_official_bighit', + 'https://tiktok.com/@tiktok' => 'https://www.tiktok.com/@tiktok', + 'http://www.tiktok.com/@tiktok' => 'https://www.tiktok.com/@tiktok', + ]; + + foreach ($values as $source => $result) { + $this->assertEquals($result, $tikTokNormalizer->normalize($source)); + } + } + + public function testAppleMusicNormalizer(): void + { + $appleMusicNormalizer = Factory::getForPlatform(AppleMusicNormalizer::PLATFORM); + + $values = [ + 'https://music.apple.com/us/artist/the-beatles/136975' => 'https://music.apple.com/artist/136975', + 'https://music.apple.com/us/artist/beatles/136975' => 'https://music.apple.com/artist/136975', + 'https://music.apple.com/artist/beatles/136975' => 'https://music.apple.com/artist/136975', + 'https://music.apple.com/artist/136975' => 'https://music.apple.com/artist/136975', + 'https://itunes.apple.com/us/artist/id136975' => 'https://music.apple.com/artist/136975', + ]; + + foreach ($values as $source => $result) { + $this->assertEquals($result, $appleMusicNormalizer->normalize($source)); + } + } + + public function testSoundcloudNormalizer(): void + { + $soundcloudNormalizer = Factory::getForPlatform(SoundcloudNormalizer::PLATFORM); + + $values = [ + 'https://soundcloud.com/kx5-music' => 'https://soundcloud.com/kx5-music', + 'https://soundcloud.com/kx5official' => 'https://soundcloud.com/kx5official', + ]; + + foreach ($values as $source => $result) { + $this->assertEquals($result, $soundcloudNormalizer->normalize($source)); + } + } + + public function testSpotifyArtistNormalizer(): void + { + $spotifyArtistNormalizer = Factory::getForPlatform(SpotifyArtistNormalizer::PLATFORM); + + $values = [ + 'https://open.spotify.com/artist/3WrFJ7ztbogyGnTHbHJFl2' => 'https://open.spotify.com/artist/3WrFJ7ztbogyGnTHbHJFl2', + 'spotify:artist:3WrFJ7ztbogyGnTHbHJFl2' => 'https://open.spotify.com/artist/3WrFJ7ztbogyGnTHbHJFl2', + ]; + + foreach ($values as $source => $result) { + $this->assertEquals($result, $spotifyArtistNormalizer->normalize($source)); + } + } + + public function testYoutubeNormalizer(): void + { + $youtubeNormalizer = Factory::getForPlatform(YoutubeNormalizer::PLATFORM); + + $values = [ + 'https://www.youtube.com/channel/UCJow9j3zvZ4vK2ZjUwZc6Fw' => 'https://www.youtube.com/channel/UCJow9j3zvZ4vK2ZjUwZc6Fw', + 'https://www.youtube.com/user/Google' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/c/Google' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/about' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/videos' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/playlists' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/community' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/channels' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/featured' => 'https://www.youtube.com/Google', + 'https://www.youtube.com/Google/live' => 'https://www.youtube.com/Google', + 'https://youtube.com/Google' => 'https://www.youtube.com/Google', + 'http://www.youtube.com/Google' => 'https://www.youtube.com/Google', + ]; + + foreach ($values as $source => $result) { + $this->assertEquals($result, $youtubeNormalizer->normalize($source)); + } + } + public function testNormalizerToId(): void { $values = [ From 9db27fcde4c8ed50ec01215b14bcabfd82a0e519 Mon Sep 17 00:00:00 2001 From: Jose Torres Date: Wed, 19 Jun 2024 17:20:25 -0400 Subject: [PATCH 3/5] Remove commented debugging. --- src/Normalizers/AbstractNormalizer.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Normalizers/AbstractNormalizer.php b/src/Normalizers/AbstractNormalizer.php index 8bd06f8..b1b0b99 100644 --- a/src/Normalizers/AbstractNormalizer.php +++ b/src/Normalizers/AbstractNormalizer.php @@ -24,13 +24,8 @@ public function normalizeToId(string $url, array $settings = []): string { $settings = array_merge($this->cleanUrlSettings, $settings); -// print_r($url); -// print_r($settings); - $url = Utils::cleanUrl($url, $settings); -// print_r($url); - $matches = $this->match($url); if (is_array($this->idPosition)) { From cb0f42d5ff2e57b66c5314f92a3d5897bd7fa42e Mon Sep 17 00:00:00 2001 From: Patrik Fuhrmann Date: Fri, 28 Jun 2024 12:58:57 +0200 Subject: [PATCH 4/5] PR improvements --- .gitignore | 2 +- README.md | 54 ++++++++++++- composer.json | 6 +- src/Factory.php | 9 +-- src/Normalizers/AbstractNormalizer.php | 4 +- src/Normalizers/AppleMusicNormalizer.php | 9 ++- src/Normalizers/FacebookPageNormalizer.php | 9 ++- src/Normalizers/FacebookProfileNormalizer.php | 7 +- src/Normalizers/Factory.php | 55 +++++++------- src/Normalizers/InstagramNormalizer.php | 7 +- src/Normalizers/LinkedinCompanyNormalizer.php | 7 +- src/Normalizers/LinkedinProfileNormalizer.php | 7 +- src/Normalizers/LinkedinSchoolNormalizer.php | 7 +- .../LinkedinShowcaseNormalizer.php | 7 +- src/Normalizers/NormalizerInterface.php | 8 +- src/Normalizers/SoundcloudNormalizer.php | 7 +- src/Normalizers/SpotifyArtistNormalizer.php | 7 +- src/Normalizers/TikTokNormalizer.php | 7 +- src/Normalizers/TwitterNormalizer.php | 18 ++--- src/Normalizers/XNormalizer.php | 7 +- src/Normalizers/YoutubeNormalizer.php | 9 ++- src/Parser.php | 21 ++---- src/Result.php | 21 ------ src/Utils.php | 6 +- tests/NormalizerFactoryTest.php | 75 +++++++++++++++++++ tests/NormalizersTest.php | 64 ++++++---------- tests/ResultTest.php | 6 +- 27 files changed, 265 insertions(+), 181 deletions(-) create mode 100644 tests/NormalizerFactoryTest.php diff --git a/.gitignore b/.gitignore index ca17bd2..3e2c495 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .idea .phpunit.cache/ .phpunit.result.cache -.composer.lock +composer.lock diff --git a/README.md b/README.md index 7ae8aa7..90eb14d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Helper package used for the validation of social links. ## Requirements -This project requires PHP 8.1 or higher with the `mbstring` extension installed. +This project requires PHP 8.2 or higher with the `mbstring` extension installed. ## Installation @@ -21,7 +21,7 @@ composer require dealroom/socials-helpers ## Usage -The `Factory` class provides a simple wrapper for the validation functionality, for example to get normalized URL: +The `Factory` class provides a simple wrapper for the validation functionality, for example, to get normalized URL: ```php use Dealroom\SocialsHelpers\Factory; @@ -47,9 +47,54 @@ echo $data; // "dealroom" ``` +## Supported Platforms + +The following platforms are supported by default: + +- Apple Music +- Facebook +- Instagram +- LinkedIn +- Twitter +- YouTube +- TikTok +- SoundCloud +- X +- Spotify + +### Registering new platforms + +To register a new normalizer, you need to create a new class that implements +the `NormalizerInterface` interface and add it to the `Factory` class. + +```php +use Dealroom\SocialsHelpers\Normalizers\NormalizerInterface; + +class CustomNormalizer implements NormalizerInterface +{ + // Implement the interface methods +} +``` + +Then add it to the `Factory` class + +```php +use Dealroom\SocialsHelpers\Normalizers\Factory; + +Factory::addNormalizer(CustomNormalizer::class); +``` + +And now, you can use it + +```php +use Dealroom\SocialsHelpers\Factory; + +$data = Factory::parseUrl('https://custom.com/Dealroom', [Parser::PLATFORM_CUSTOM])->getNormalizedUrl(); +``` + ## Testing -PHPUnit is used for testing, just run: +PHPUnit is used for testing, run: ```bash ./vendor/bin/phpunit @@ -58,4 +103,5 @@ PHPUnit is used for testing, just run: ## Releases and CI/CD The release is done automatically using GitHub actions on every push to the `main` branch. -After the release is done, a new tag is created and pushed to GitHub which triggers a new release in [packagist](https://packagist.org/). +After the release is done, a new tag is created and pushed to GitHub, +which triggers a new release in [packagist](https://packagist.org/). diff --git a/composer.json b/composer.json index cd3ce6a..c66a5fa 100644 --- a/composer.json +++ b/composer.json @@ -1,15 +1,15 @@ { "name": "dealroom/socials-helpers", - "description": "Helper package used for the validation of social links", + "description": "Helper package used for the validation and normalization of social media links", "type": "library", "license": "MIT", "keywords": ["social", "linkedin", "facebook", "twitter"], "require": { - "php": ">=8.1", + "php": ">=8.2", "ext-mbstring": "*" }, "require-dev": { - "phpunit/phpunit": "^10.3" + "phpunit/phpunit": "^11.2" }, "scripts": { "test": "vendor/bin/phpunit" diff --git a/src/Factory.php b/src/Factory.php index 7a00061..c5bfaa1 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -6,13 +6,8 @@ class Factory { - /** - * @param string $url - * @param array $allowedTypes - * @return Result - */ - public static function parseUrl(string $url, array $allowedTypes = []): Result + public static function parseUrl(string $url, array $allowedPlatforms = []): Result { - return (new Parser())->parseUrl($url, $allowedTypes); + return (new Parser())->parseUrl($url, $allowedPlatforms); } } diff --git a/src/Normalizers/AbstractNormalizer.php b/src/Normalizers/AbstractNormalizer.php index b1b0b99..18f5e6a 100644 --- a/src/Normalizers/AbstractNormalizer.php +++ b/src/Normalizers/AbstractNormalizer.php @@ -30,7 +30,7 @@ public function normalizeToId(string $url, array $settings = []): string if (is_array($this->idPosition)) { foreach ($this->idPosition as $position) { - if(isset($matches[$position])) { + if (isset($matches[$position])) { return $matches[$position]; } } @@ -60,7 +60,7 @@ protected function match(string $url): array if (!$result) { throw new NormalizeException( - sprintf("%s pattern didn't match for %s", static::PLATFORM_NAME, $url) + sprintf("%s pattern didn't match for '%s'", static::getPlatform(), $url) ); } diff --git a/src/Normalizers/AppleMusicNormalizer.php b/src/Normalizers/AppleMusicNormalizer.php index 77e7f9d..e6c67b1 100644 --- a/src/Normalizers/AppleMusicNormalizer.php +++ b/src/Normalizers/AppleMusicNormalizer.php @@ -6,11 +6,14 @@ class AppleMusicNormalizer extends AbstractNormalizer { - public const PLATFORM = 'apple_music'; - - public const PLATFORM_NAME = 'Apple Music Artist'; + public static function getPlatform(): string + { + return 'apple_music'; + } + // phpcs:disable Generic.Files.LineLength.TooLong protected string $pattern = '/https?:\/\/(?:itunes|music)\.apple\.com\/(?:[\pL]{2}\/)?artist\/(?:[\pL\d_\-\%\.]+\/)?(?:id)?([\d]+)/'; + // phpcs:enable Generic.Files.LineLength.TooLong protected string $normalizedUrl = 'https://music.apple.com/artist/%s'; diff --git a/src/Normalizers/FacebookPageNormalizer.php b/src/Normalizers/FacebookPageNormalizer.php index 23c63a1..be2acbb 100644 --- a/src/Normalizers/FacebookPageNormalizer.php +++ b/src/Normalizers/FacebookPageNormalizer.php @@ -6,11 +6,14 @@ class FacebookPageNormalizer extends AbstractNormalizer { - public const PLATFORM = 'facebook_page'; - - public const PLATFORM_NAME = 'Facebook Page'; + public static function getPlatform(): string + { + return 'facebook_page'; + } + // phpcs:disable Generic.Files.LineLength.TooLong protected string $pattern = '/https?:\/\/(?:www\.|m\.|mobile\.|business\.|web\.|p-upload\.|[a-z]{2}-[a-z]{2}\.)?(?:facebook|fb)\.com\/(?!home\.php)(?:sharer\/|sharer.php|share.php|people\/_\/|profile\.php|pages\/)?(?:(?:([\pL][\pL0-9_\-\+\.\%]+)\/?)+)(\d+)?\/?/u'; + // phpcs:enable Generic.Files.LineLength.TooLong protected string $normalizedUrl = 'https://www.facebook.com/%s'; diff --git a/src/Normalizers/FacebookProfileNormalizer.php b/src/Normalizers/FacebookProfileNormalizer.php index c33c690..0ddc7e1 100644 --- a/src/Normalizers/FacebookProfileNormalizer.php +++ b/src/Normalizers/FacebookProfileNormalizer.php @@ -6,9 +6,10 @@ class FacebookProfileNormalizer extends AbstractNormalizer { - public const PLATFORM = 'facebook_profile'; - - public const PLATFORM_NAME = 'Facebook Profile'; + public static function getPlatform(): string + { + return 'facebook_profile'; + } protected string $pattern = '/http(s)?:\/\/(www\.)?(facebook|fb)\.com\/(people\/_\/|profile\.php\?id=)(\d+)\/?/'; diff --git a/src/Normalizers/Factory.php b/src/Normalizers/Factory.php index 703c929..43c3d01 100644 --- a/src/Normalizers/Factory.php +++ b/src/Normalizers/Factory.php @@ -8,42 +8,41 @@ class Factory { - public static array $normalizers = [ - FacebookPageNormalizer::PLATFORM => FacebookPageNormalizer::class, - FacebookProfileNormalizer::PLATFORM => FacebookProfileNormalizer::class, - InstagramNormalizer::PLATFORM => InstagramNormalizer::class, - TikTokNormalizer::PLATFORM => TikTokNormalizer::class, - TwitterNormalizer::PLATFORM => TwitterNormalizer::class, - XNormalizer::PLATFORM => XNormalizer::class, - LinkedinCompanyNormalizer::PLATFORM => LinkedinCompanyNormalizer::class, - LinkedinShowcaseNormalizer::PLATFORM => LinkedinShowcaseNormalizer::class, - LinkedinSchoolNormalizer::PLATFORM => LinkedinSchoolNormalizer::class, - LinkedinProfileNormalizer::PLATFORM => LinkedinProfileNormalizer::class, - AppleMusicNormalizer::PLATFORM => AppleMusicNormalizer::class, - SoundcloudNormalizer::PLATFORM => SoundcloudNormalizer::class, - SpotifyArtistNormalizer::PLATFORM => SpotifyArtistNormalizer::class, - YoutubeNormalizer::PLATFORM => YoutubeNormalizer::class, + private static array $normalizers = [ + AppleMusicNormalizer::class, + FacebookPageNormalizer::class, + FacebookProfileNormalizer::class, + InstagramNormalizer::class, + LinkedinCompanyNormalizer::class, + LinkedinProfileNormalizer::class, + LinkedinSchoolNormalizer::class, + LinkedinShowcaseNormalizer::class, + SoundcloudNormalizer::class, + SpotifyArtistNormalizer::class, + TikTokNormalizer::class, + TwitterNormalizer::class, + XNormalizer::class, + YoutubeNormalizer::class, ]; - /** - * @param string $platform - * - * @return NormalizerInterface - */ public static function getForPlatform(string $platform): NormalizerInterface { - if (!isset(self::$normalizers[$platform])) { - throw new NormalizeException(sprintf('No normalizer found for platform %s', $platform)); + foreach (self::$normalizers as $normalizer) { + if ($normalizer::getPlatform() === $platform) { + return new $normalizer(); + } } - return new self::$normalizers[$platform](); + throw new NormalizeException(sprintf('No normalizer found for platform %s', $platform)); } - public static function registerNormalizer($normalizer): void + public static function addNormalizer(NormalizerInterface $normalizer): void { - if (!is_a($normalizer, NormalizerInterface::class, true)) { - throw new NormalizeException(sprintf('Normalizer %s must implement NormalizerInterface', $normalizer)); - } - self::$normalizers[$normalizer::PLATFORM] = $normalizer::class; + self::$normalizers[] = $normalizer::class; + } + + public static function getNormalizers(): array + { + return self::$normalizers; } } diff --git a/src/Normalizers/InstagramNormalizer.php b/src/Normalizers/InstagramNormalizer.php index 0bdb4d2..9b6ccd8 100644 --- a/src/Normalizers/InstagramNormalizer.php +++ b/src/Normalizers/InstagramNormalizer.php @@ -6,9 +6,10 @@ class InstagramNormalizer extends AbstractNormalizer { - public const PLATFORM = 'instagram'; - - public const PLATFORM_NAME = 'Instagram Profile'; + public static function getPlatform(): string + { + return 'instagram'; + } protected string $pattern = '/https?:\/\/(?:www\.)?instagram\.com\/(?!about|legal|explore|web)([\pL\d\_\.]{1,30})/'; diff --git a/src/Normalizers/LinkedinCompanyNormalizer.php b/src/Normalizers/LinkedinCompanyNormalizer.php index 95b55aa..f362ed6 100644 --- a/src/Normalizers/LinkedinCompanyNormalizer.php +++ b/src/Normalizers/LinkedinCompanyNormalizer.php @@ -6,9 +6,10 @@ class LinkedinCompanyNormalizer extends AbstractNormalizer { - public const PLATFORM = 'linkedin_company'; - - public const PLATFORM_NAME = 'Linkedin Company'; + public static function getPlatform(): string + { + return 'linkedin_company'; + } protected string $pattern = '/http(s)?:\/\/(www\.)?linkedin\.com\/company\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; diff --git a/src/Normalizers/LinkedinProfileNormalizer.php b/src/Normalizers/LinkedinProfileNormalizer.php index 48e7c0f..beaf6c4 100644 --- a/src/Normalizers/LinkedinProfileNormalizer.php +++ b/src/Normalizers/LinkedinProfileNormalizer.php @@ -6,9 +6,10 @@ class LinkedinProfileNormalizer extends AbstractNormalizer { - public const PLATFORM = 'linkedin_profile'; - - public const PLATFORM_NAME = 'Linkedin Profile'; + public static function getPlatform(): string + { + return 'linkedin_profile'; + } protected string $pattern = '/(?:https?:)?\/\/(?:[\w]+\.)?linkedin\.com\/in\/([\w\-\_À-ÿ%]+)\/?/u'; diff --git a/src/Normalizers/LinkedinSchoolNormalizer.php b/src/Normalizers/LinkedinSchoolNormalizer.php index b9c7313..ffa7a7d 100644 --- a/src/Normalizers/LinkedinSchoolNormalizer.php +++ b/src/Normalizers/LinkedinSchoolNormalizer.php @@ -6,9 +6,10 @@ class LinkedinSchoolNormalizer extends AbstractNormalizer { - public const PLATFORM = 'linkedin_school'; - - public const PLATFORM_NAME = 'Linkedin School'; + public static function getPlatform(): string + { + return 'linkedin_school'; + } protected string $pattern = '/http(s)?:\/\/(www\.)?linkedin\.com\/school\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; diff --git a/src/Normalizers/LinkedinShowcaseNormalizer.php b/src/Normalizers/LinkedinShowcaseNormalizer.php index 646d847..2b1eff9 100644 --- a/src/Normalizers/LinkedinShowcaseNormalizer.php +++ b/src/Normalizers/LinkedinShowcaseNormalizer.php @@ -6,9 +6,10 @@ class LinkedinShowcaseNormalizer extends AbstractNormalizer { - public const PLATFORM = 'linkedin_showcase'; - - public const PLATFORM_NAME = 'Linkedin Showcase'; + public static function getPlatform(): string + { + return 'linkedin_showcase'; + } protected string $pattern = '/http(s)?:\/\/(www\.)?linkedin\.com\/showcase\/?([\p{L}\d&\'.\-–_®]+)\/?/u'; diff --git a/src/Normalizers/NormalizerInterface.php b/src/Normalizers/NormalizerInterface.php index e85121c..0d640d6 100644 --- a/src/Normalizers/NormalizerInterface.php +++ b/src/Normalizers/NormalizerInterface.php @@ -4,9 +4,15 @@ interface NormalizerInterface { + /** + * Name of the platform e.g., facebook, instagram, TikTok, etc. + * Note: must be unique among all registered normalizers + */ + public static function getPlatform(): string; + public function normalize(string $url): string; - public function normalizeToId(string $url, array $settings): ?string; + public function normalizeToId(string $url, array $settings = []): ?string; public function getPattern(): string; diff --git a/src/Normalizers/SoundcloudNormalizer.php b/src/Normalizers/SoundcloudNormalizer.php index 788fe58..45832fe 100644 --- a/src/Normalizers/SoundcloudNormalizer.php +++ b/src/Normalizers/SoundcloudNormalizer.php @@ -6,9 +6,10 @@ class SoundcloudNormalizer extends AbstractNormalizer { - public const PLATFORM = 'soundcloud'; - - public const PLATFORM_NAME = 'Soundcloud Profile'; + public static function getPlatform(): string + { + return 'soundcloud'; + } protected string $pattern = '/https?:\/\/soundcloud\.com\/([\pL\d\-\_]+)/'; diff --git a/src/Normalizers/SpotifyArtistNormalizer.php b/src/Normalizers/SpotifyArtistNormalizer.php index 3843a8a..88564e1 100644 --- a/src/Normalizers/SpotifyArtistNormalizer.php +++ b/src/Normalizers/SpotifyArtistNormalizer.php @@ -6,9 +6,10 @@ class SpotifyArtistNormalizer extends AbstractNormalizer { - public const PLATFORM = 'spotify_artist'; - - public const PLATFORM_NAME = 'Spotify Artist'; + public static function getPlatform(): string + { + return 'spotify_artist'; + } protected string $pattern = '/(?:https?:\/\/open.spotify.com\/artist\/|spotify:artist:)([a-zA-Z0-9]+)/'; diff --git a/src/Normalizers/TikTokNormalizer.php b/src/Normalizers/TikTokNormalizer.php index 9c20015..03b34f3 100644 --- a/src/Normalizers/TikTokNormalizer.php +++ b/src/Normalizers/TikTokNormalizer.php @@ -6,9 +6,10 @@ class TikTokNormalizer extends AbstractNormalizer { - public const PLATFORM = 'tiktok'; - - public const PLATFORM_NAME = 'TikTok Profile'; + public static function getPlatform(): string + { + return 'tiktok'; + } protected string $pattern = '/https?:\/\/(?:www\.)?tiktok\.com\/(@[\pL\d\_\.]{1,24})/'; diff --git a/src/Normalizers/TwitterNormalizer.php b/src/Normalizers/TwitterNormalizer.php index 9c24906..2551952 100644 --- a/src/Normalizers/TwitterNormalizer.php +++ b/src/Normalizers/TwitterNormalizer.php @@ -8,9 +8,10 @@ class TwitterNormalizer extends AbstractNormalizer { - public const PLATFORM = 'twitter'; - - public const PLATFORM_NAME = 'Twitter'; + public static function getPlatform(): string + { + return 'twitter'; + } protected string $pattern = '/https?:\/\/(?:www\.)?twitter\.com\/@?(?:#!\/)?([A-z0-9_]+)\/?/'; @@ -18,30 +19,25 @@ class TwitterNormalizer extends AbstractNormalizer protected array|int $idPosition = 1; - /** - * @param string $url - * - * @return array - */ protected function match(string $url): array { $result = preg_match($this->getPattern(), $url, $matches); if (!$result) { throw new NormalizeException( - sprintf("%s pattern didn't match for %s", static::PLATFORM_NAME, $url) + sprintf("%s pattern didn't match for %s", static::getPlatform(), $url) ); } if ($matches[1] === 'share') { throw new NormalizeException( - sprintf('%s name can not be equal to share', static::PLATFORM_NAME) + sprintf('%s name can not be equal to share', static::getPlatform()) ); } if (strlen($matches[1]) > 15) { throw new NormalizeException( - sprintf('%s name can not be longer than 15 chars: %s', static::PLATFORM_NAME, $matches[4]) + sprintf('%s name can not be longer than 15 chars: %s', static::getPlatform(), $matches[4]) ); } diff --git a/src/Normalizers/XNormalizer.php b/src/Normalizers/XNormalizer.php index 348789a..957c9d2 100644 --- a/src/Normalizers/XNormalizer.php +++ b/src/Normalizers/XNormalizer.php @@ -6,9 +6,10 @@ class XNormalizer extends TwitterNormalizer { - public const PLATFORM = 'x'; - - public const PLATFORM_NAME = 'X'; + public static function getPlatform(): string + { + return 'x'; + } protected string $pattern = '/https?:\/\/(?:www\.)?x\.com\/@?(?:#!\/)?([A-z0-9_]+)\/?/'; diff --git a/src/Normalizers/YoutubeNormalizer.php b/src/Normalizers/YoutubeNormalizer.php index 33625fa..f1c426d 100644 --- a/src/Normalizers/YoutubeNormalizer.php +++ b/src/Normalizers/YoutubeNormalizer.php @@ -6,11 +6,14 @@ class YoutubeNormalizer extends AbstractNormalizer { - public const PLATFORM = 'youtube'; - - public const PLATFORM_NAME = 'Youtube Channel'; + public static function getPlatform(): string + { + return 'youtube'; + } + // phpcs:disable Generic.Files.LineLength.TooLong protected string $pattern = '/https?:\/\/(?:www\.)?youtube.com\/(?:c\/|user\/)?((?:channel\/UC)?[\pL\d_\-\+\.\%\@]+)/u'; + // phpcs:enable Generic.Files.LineLength.TooLong protected string $normalizedUrl = 'https://www.youtube.com/%s'; diff --git a/src/Parser.php b/src/Parser.php index e68be2c..877dc32 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -10,15 +10,9 @@ class Parser { - /** - * @param string $url - * @param array $allowedPlatforms - * @return Result - */ public function parseUrl(string $url, array $allowedPlatforms = []): Result { $url = Utils::cleanUrl($url); - if (!Utils::isValidUrl($url)) { throw new InvalidUrlException(sprintf('Invalid url %s', $url)); } @@ -28,20 +22,17 @@ public function parseUrl(string $url, array $allowedPlatforms = []): Result return new Result($platform, $url); } - /** - * @param string $url - * @param array $allowedTypes - * @return string - */ - private function identifyPlatform(string $url, array $allowedTypes = []): string + private function identifyPlatform(string $url, array $allowedPlatforms = []): string { - foreach (Factory::$normalizers as $platform => $normalizer) { - if ($allowedTypes && !in_array($platform, $allowedTypes)) { + foreach (Factory::getNormalizers() as $normalizer) { + $platform = $normalizer::getPlatform(); + if (!empty($allowedPlatforms) && !in_array($platform, $allowedPlatforms)) { continue; } + $normalizerInstance = Factory::getForPlatform($platform); if (preg_match($normalizerInstance->getPattern(), rawurldecode($url))) { - return $normalizerInstance::PLATFORM; + return $normalizerInstance::getPlatform(); } } diff --git a/src/Result.php b/src/Result.php index fe15e36..05c7514 100644 --- a/src/Result.php +++ b/src/Result.php @@ -15,12 +15,6 @@ class Result private string $id; private NormalizerInterface $normalizer; - /** - * Result constructor. - * - * @param string $platform - * @param string $url - */ public function __construct(string $platform, string $url) { $this->platform = $platform; @@ -30,41 +24,26 @@ public function __construct(string $platform, string $url) $this->id = $this->normalizer->normalizeToId($this->url); } - /** - * @return string - */ public function getPlatform(): string { return $this->platform; } - /** - * @return string - */ public function getUrl(): string { return $this->url; } - /** - * @return string - */ public function getNormalizedUrl(): string { return $this->normalizedUrl; } - /** - * @return string - */ public function getId(): string { return $this->id; } - /** - * @return Normalizers\NormalizerInterface - */ private function getNormalizer(): NormalizerInterface { return NormalizerFactory::getForPlatform($this->platform); diff --git a/src/Utils.php b/src/Utils.php index 0265056..f0effd2 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -6,10 +6,6 @@ class Utils { - /** - * @param string $url - * @return string - */ public static function cleanUrl(string $url, array $settings = []): string { $settings = array_merge([ @@ -28,7 +24,7 @@ public static function cleanUrl(string $url, array $settings = []): string // Clean usages of #! $url = str_replace('#!/', '/', $url); - // Clean weird double slashes // + // Clean double slashes // if (strlen($url) > 7) { while (strpos($url, '//', 7) !== false) { $url = substr_replace($url, '', strpos($url, '//', 7), 1); diff --git a/tests/NormalizerFactoryTest.php b/tests/NormalizerFactoryTest.php new file mode 100644 index 0000000..4c149be --- /dev/null +++ b/tests/NormalizerFactoryTest.php @@ -0,0 +1,75 @@ +assertInstanceOf(TwitterNormalizer::class, $twitterNormalizer); + $this->assertInstanceOf(FacebookPageNormalizer::class, $facebookPageNormalizer); + $this->assertInstanceOf(FacebookProfileNormalizer::class, $facebookProfileNormalizer); + $this->assertInstanceOf(LinkedinCompanyNormalizer::class, $linkedinCompanyProfileNormalizer); + $this->assertInstanceOf(NormalizerInterface::class, $twitterNormalizer); + $this->assertInstanceOf(NormalizerInterface::class, $facebookPageNormalizer); + $this->assertInstanceOf(NormalizerInterface::class, $facebookProfileNormalizer); + $this->assertInstanceOf(NormalizerInterface::class, $linkedinCompanyProfileNormalizer); + } + + public function testNormalizersFactoryException(): void + { + $this->expectException(NormalizeException::class); + + Factory::getForPlatform('foo'); + } + + public function testAddNormalizer(): void + { + $fakeNormalizer = new class implements NormalizerInterface { + public static function getPlatform(): string + { + return 'foo'; + } + + public function normalize(string $url): string + { + return $url; + } + + public function normalizeToId(string $url, array $settings = []): string + { + return $url; + } + + public function getPattern(): string + { + return '/foo/'; + } + + public function setPattern(string $pattern): void + { + // Do nothing + } + }; + + Factory::addNormalizer($fakeNormalizer); + + $this->assertInstanceOf($fakeNormalizer::class, Factory::getForPlatform($fakeNormalizer::getPlatform())); + } +} diff --git a/tests/NormalizersTest.php b/tests/NormalizersTest.php index 4ca3422..389a01e 100644 --- a/tests/NormalizersTest.php +++ b/tests/NormalizersTest.php @@ -14,7 +14,6 @@ use Dealroom\SocialsHelpers\Normalizers\LinkedinProfileNormalizer; use Dealroom\SocialsHelpers\Normalizers\LinkedinSchoolNormalizer; use Dealroom\SocialsHelpers\Normalizers\LinkedinShowcaseNormalizer; -use Dealroom\SocialsHelpers\Normalizers\NormalizerInterface; use Dealroom\SocialsHelpers\Normalizers\SoundcloudNormalizer; use Dealroom\SocialsHelpers\Normalizers\SpotifyArtistNormalizer; use Dealroom\SocialsHelpers\Normalizers\TikTokNormalizer; @@ -26,26 +25,9 @@ // phpcs:disable Generic.Files.LineLength.TooLong class NormalizersTest extends TestCase { - public function testNormalizersFactory(): void - { - $twitterNormalizer = Factory::getForPlatform(TwitterNormalizer::PLATFORM); - $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::PLATFORM); - $facebookProfileNormalizer = Factory::getForPlatform(FacebookProfileNormalizer::PLATFORM); - $linkedinCompanyProfileNormalizer = Factory::getForPlatform(LinkedinCompanyNormalizer::PLATFORM); - - $this->assertInstanceOf(TwitterNormalizer::class, $twitterNormalizer); - $this->assertInstanceOf(FacebookPageNormalizer::class, $facebookPageNormalizer); - $this->assertInstanceOf(FacebookProfileNormalizer::class, $facebookProfileNormalizer); - $this->assertInstanceOf(LinkedinCompanyNormalizer::class, $linkedinCompanyProfileNormalizer); - $this->assertInstanceOf(NormalizerInterface::class, $twitterNormalizer); - $this->assertInstanceOf(NormalizerInterface::class, $facebookPageNormalizer); - $this->assertInstanceOf(NormalizerInterface::class, $facebookProfileNormalizer); - $this->assertInstanceOf(NormalizerInterface::class, $linkedinCompanyProfileNormalizer); - } - public function testTwitterNormalizer(): void { - $twitterNormalizer = Factory::getForPlatform(TwitterNormalizer::PLATFORM); + $twitterNormalizer = Factory::getForPlatform(TwitterNormalizer::getPlatform()); $values = [ 'http://www.twitter.com/codeschool/dasd?dsadasd' => 'https://twitter.com/codeschool', @@ -71,7 +53,7 @@ public function testTwitterNormalizer(): void public function testXNormalizer(): void { - $twitterNormalizer = Factory::getForPlatform(XNormalizer::PLATFORM); + $twitterNormalizer = Factory::getForPlatform(XNormalizer::getPlatform()); $values = [ 'http://www.x.com/codeschool/dasd?dsadasd' => 'https://x.com/codeschool', @@ -97,7 +79,7 @@ public function testXNormalizer(): void public function testFacebookPageNormalizer(): void { - $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::PLATFORM); + $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::getPlatform()); $values = [ @@ -131,7 +113,7 @@ public function testFacebookPageNormalizer(): void public function testFacebookPageNormalizerErrors(): void { - $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::PLATFORM); + $facebookPageNormalizer = Factory::getForPlatform(FacebookPageNormalizer::getPlatform()); $values = [ 'http://www.facebook.com/home.php?tests#!/pages/dealmarket/157833714232772', @@ -145,7 +127,7 @@ public function testFacebookPageNormalizerErrors(): void public function testFacebookProfileNormalizer(): void { - $facebookProfileNormalizer = Factory::getForPlatform(FacebookProfileNormalizer::PLATFORM); + $facebookProfileNormalizer = Factory::getForPlatform(FacebookProfileNormalizer::getPlatform()); $values = [ 'http://www.facebook.com/people/_/100000049946330' => 'https://www.facebook.com/profile.php?id=100000049946330', @@ -163,7 +145,7 @@ public function testFacebookProfileNormalizer(): void //InstagramNormalizer public function testInstagramNormalizer(): void { - $instagramNormalizer = Factory::getForPlatform(InstagramNormalizer::PLATFORM); + $instagramNormalizer = Factory::getForPlatform(InstagramNormalizer::getPlatform()); $values = [ 'https://www.instagram.com/kevin' => 'https://www.instagram.com/kevin', @@ -179,7 +161,7 @@ public function testInstagramNormalizer(): void public function testLinkedinCompanyNormalizer(): void { - $linkedinCompanyProfileNormalizer = Factory::getForPlatform(LinkedinCompanyNormalizer::PLATFORM); + $linkedinCompanyProfileNormalizer = Factory::getForPlatform(LinkedinCompanyNormalizer::getPlatform()); $values = [ 'https://www.linkedin.com/company/dealroom/' => 'https://www.linkedin.com/company/dealroom/', @@ -204,7 +186,7 @@ public function testLinkedinCompanyNormalizer(): void public function testLinkedinShowcaseNormalizer(): void { - $linkedinShowcaseNormalizer = Factory::getForPlatform(LinkedinShowcaseNormalizer::PLATFORM); + $linkedinShowcaseNormalizer = Factory::getForPlatform(LinkedinShowcaseNormalizer::getPlatform()); $values = [ 'https://www.linkedin.com/showcase/dealroom/' => 'https://www.linkedin.com/showcase/dealroom/', @@ -229,7 +211,7 @@ public function testLinkedinShowcaseNormalizer(): void public function testLinkedinSchoolNormalizer(): void { - $linkedinSchoolNormalizer = Factory::getForPlatform(LinkedinSchoolNormalizer::PLATFORM); + $linkedinSchoolNormalizer = Factory::getForPlatform(LinkedinSchoolNormalizer::getPlatform()); $values = [ 'https://www.linkedin.com/school/dealroom/' => 'https://www.linkedin.com/school/dealroom/', @@ -254,7 +236,7 @@ public function testLinkedinSchoolNormalizer(): void public function testLinkedinProfileNormalizer(): void { - $linkedinSchoolNormalizer = Factory::getForPlatform(LinkedinProfileNormalizer::PLATFORM); + $linkedinProfileNormalizer = Factory::getForPlatform(LinkedinProfileNormalizer::getPlatform()); $values = [ 'https://www.linkedin.com/in/dealroom/' => 'https://www.linkedin.com/in/dealroom/', @@ -265,13 +247,13 @@ public function testLinkedinProfileNormalizer(): void ]; foreach ($values as $source => $result) { - $this->assertEquals($result, $linkedinSchoolNormalizer->normalize($source)); + $this->assertEquals($result, $linkedinProfileNormalizer->normalize($source)); } } public function testTikTokNormalizer(): void { - $tikTokNormalizer = Factory::getForPlatform(TikTokNormalizer::PLATFORM); + $tikTokNormalizer = Factory::getForPlatform(TikTokNormalizer::getPlatform()); $values = [ 'https://www.tiktok.com/@khaby.lame' => 'https://www.tiktok.com/@khaby.lame', @@ -288,7 +270,7 @@ public function testTikTokNormalizer(): void public function testAppleMusicNormalizer(): void { - $appleMusicNormalizer = Factory::getForPlatform(AppleMusicNormalizer::PLATFORM); + $appleMusicNormalizer = Factory::getForPlatform(AppleMusicNormalizer::getPlatform()); $values = [ 'https://music.apple.com/us/artist/the-beatles/136975' => 'https://music.apple.com/artist/136975', @@ -305,7 +287,7 @@ public function testAppleMusicNormalizer(): void public function testSoundcloudNormalizer(): void { - $soundcloudNormalizer = Factory::getForPlatform(SoundcloudNormalizer::PLATFORM); + $soundcloudNormalizer = Factory::getForPlatform(SoundcloudNormalizer::getPlatform()); $values = [ 'https://soundcloud.com/kx5-music' => 'https://soundcloud.com/kx5-music', @@ -319,7 +301,7 @@ public function testSoundcloudNormalizer(): void public function testSpotifyArtistNormalizer(): void { - $spotifyArtistNormalizer = Factory::getForPlatform(SpotifyArtistNormalizer::PLATFORM); + $spotifyArtistNormalizer = Factory::getForPlatform(SpotifyArtistNormalizer::getPlatform()); $values = [ 'https://open.spotify.com/artist/3WrFJ7ztbogyGnTHbHJFl2' => 'https://open.spotify.com/artist/3WrFJ7ztbogyGnTHbHJFl2', @@ -333,7 +315,7 @@ public function testSpotifyArtistNormalizer(): void public function testYoutubeNormalizer(): void { - $youtubeNormalizer = Factory::getForPlatform(YoutubeNormalizer::PLATFORM); + $youtubeNormalizer = Factory::getForPlatform(YoutubeNormalizer::getPlatform()); $values = [ 'https://www.youtube.com/channel/UCJow9j3zvZ4vK2ZjUwZc6Fw' => 'https://www.youtube.com/channel/UCJow9j3zvZ4vK2ZjUwZc6Fw', @@ -360,13 +342,13 @@ public function testYoutubeNormalizer(): void public function testNormalizerToId(): void { $values = [ - 'https://twitter.com/codeschool' => [TwitterNormalizer::PLATFORM, 'codeschool'], - 'https://www.facebook.com/dizzain' => [FacebookPageNormalizer::PLATFORM, 'dizzain'], - 'https://www.facebook.com/profile.php?id=1294422029' => [FacebookProfileNormalizer::PLATFORM, '1294422029'], - 'https://www.linkedin.com/company/dealroom/' => [LinkedinCompanyNormalizer::PLATFORM, 'dealroom'], - 'https://www.linkedin.com/showcase/dealroom/' => [LinkedinShowcaseNormalizer::PLATFORM, 'dealroom'], - 'https://www.linkedin.com/school/dealroom//' => [LinkedinSchoolNormalizer::PLATFORM, 'dealroom'], - 'https://www.linkedin.com/in/dealroom//' => [LinkedinProfileNormalizer::PLATFORM, 'dealroom'], + 'https://twitter.com/codeschool' => [TwitterNormalizer::getPlatform(), 'codeschool'], + 'https://www.facebook.com/dizzain' => [FacebookPageNormalizer::getPlatform(), 'dizzain'], + 'https://www.facebook.com/profile.php?id=1294422029' => [FacebookProfileNormalizer::getPlatform(), '1294422029'], + 'https://www.linkedin.com/company/dealroom/' => [LinkedinCompanyNormalizer::getPlatform(), 'dealroom'], + 'https://www.linkedin.com/showcase/dealroom/' => [LinkedinShowcaseNormalizer::getPlatform(), 'dealroom'], + 'https://www.linkedin.com/school/dealroom//' => [LinkedinSchoolNormalizer::getPlatform(), 'dealroom'], + 'https://www.linkedin.com/in/dealroom//' => [LinkedinProfileNormalizer::getPlatform(), 'dealroom'], ]; foreach ($values as $url => $row) { diff --git a/tests/ResultTest.php b/tests/ResultTest.php index b91dbdc..742c22a 100644 --- a/tests/ResultTest.php +++ b/tests/ResultTest.php @@ -16,9 +16,9 @@ public function testResultMethods(): void $result = Factory::parseUrl($url); - $this->assertEquals(TwitterNormalizer::PLATFORM, $result->getPlatform()); -// $this->assertEquals(strtolower($url), $result->getUrl()); + $this->assertEquals(TwitterNormalizer::getPlatform(), $result->getPlatform()); + $this->assertEquals($url, $result->getUrl()); $this->assertEquals('https://twitter.com/dealroom', $result->getNormalizedUrl()); - + $this->assertEquals('dealroom', $result->getId()); } } From 339623676d73ee6fbb6632dae418fb9d09f267a5 Mon Sep 17 00:00:00 2001 From: Patrik Fuhrmann Date: Fri, 28 Jun 2024 13:22:03 +0200 Subject: [PATCH 5/5] Simplify --- src/Normalizers/AbstractNormalizer.php | 5 ----- src/Normalizers/NormalizerInterface.php | 2 -- tests/NormalizerFactoryTest.php | 5 ----- 3 files changed, 12 deletions(-) diff --git a/src/Normalizers/AbstractNormalizer.php b/src/Normalizers/AbstractNormalizer.php index 18f5e6a..6f2fab9 100644 --- a/src/Normalizers/AbstractNormalizer.php +++ b/src/Normalizers/AbstractNormalizer.php @@ -45,11 +45,6 @@ public function getPattern(): string return $this->pattern; } - public function setPattern(string $pattern): void - { - $this->pattern = $pattern; - } - protected function match(string $url): array { $result = preg_match( diff --git a/src/Normalizers/NormalizerInterface.php b/src/Normalizers/NormalizerInterface.php index 0d640d6..15ef988 100644 --- a/src/Normalizers/NormalizerInterface.php +++ b/src/Normalizers/NormalizerInterface.php @@ -15,6 +15,4 @@ public function normalize(string $url): string; public function normalizeToId(string $url, array $settings = []): ?string; public function getPattern(): string; - - public function setPattern(string $pattern): void; } diff --git a/tests/NormalizerFactoryTest.php b/tests/NormalizerFactoryTest.php index 4c149be..d369737 100644 --- a/tests/NormalizerFactoryTest.php +++ b/tests/NormalizerFactoryTest.php @@ -61,11 +61,6 @@ public function getPattern(): string { return '/foo/'; } - - public function setPattern(string $pattern): void - { - // Do nothing - } }; Factory::addNormalizer($fakeNormalizer);