'_s', // 75x75 'LargeSquare' => '_q', // 150x150 'Thumbnail' => '_t', // 100 on longest side 'Small' => '_m', // 240 on longest side 'Small320' => '_n', // 320 on longest side 'Medium' => '', // 500 on longest side 'Medium640' => '_z', // 640 on longest side 'Medium800' => '_c', // 800 on longest side 'Large' => '_b', // 1024 on longest side 'Large1600' => '_h', // 1600 on longest side 'Large2048' => '_k', // 2048 on longest side 'Original' => '_o', // original image ]; /** * Parse a Flickr URL and extract photo information * * @param string $url Flickr URL * @return array|null Photo info or null if not a valid Flickr URL */ public function parse($url) { $url = trim($url); // Direct image URL if (preg_match('/staticflickr\.com\/\d+\/(\d+)_([a-f0-9]+)(_[a-z])?\.(\w+)/i', $url, $matches)) { return [ 'photo_id' => $matches[1], 'secret' => $matches[2], 'size_suffix' => isset($matches[3]) ? $matches[3] : '', 'format' => $matches[4], 'type' => 'direct', 'original_url' => $url, ]; } // Photo page URL if (preg_match('/flickr\.com\/photos\/[^\/]+\/(\d+)/i', $url, $matches)) { return [ 'photo_id' => $matches[1], 'type' => 'page', 'original_url' => $url, ]; } // Short URL (flic.kr) if (preg_match('/flic\.kr\/p\/([a-zA-Z0-9]+)/i', $url, $matches)) { $photoId = $this->decodeBase58($matches[1]); return [ 'photo_id' => $photoId, 'type' => 'short', 'original_url' => $url, ]; } return null; } /** * Parse multiple URLs (one per line or comma-separated) * * @param string $input Input text with URLs * @return array Array of parsed photo info */ public function parseMultiple($input) { $results = []; // Split by newlines and commas $lines = preg_split('/[\r\n,]+/', $input); foreach ($lines as $line) { $url = trim($line); if (empty($url)) continue; $parsed = $this->parse($url); if ($parsed) { $results[] = $parsed; } } return $results; } /** * Build a direct image URL from photo info * * @param array $photoInfo Photo information * @param string $size Size name from SIZES constant * @return string Direct image URL */ public function buildImageUrl($photoInfo, $size = 'Large') { $suffix = isset(self::SIZES[$size]) ? self::SIZES[$size] : self::SIZES['Large']; $server = isset($photoInfo['server']) ? $photoInfo['server'] : '65535'; $photoId = $photoInfo['photo_id']; $secret = isset($photoInfo['secret']) ? $photoInfo['secret'] : (isset($photoInfo['originalsecret']) ? $photoInfo['originalsecret'] : ''); $format = isset($photoInfo['format']) ? $photoInfo['format'] : (isset($photoInfo['originalformat']) ? $photoInfo['originalformat'] : 'jpg'); // For original size, use originalsecret if available if ($size === 'Original' && isset($photoInfo['originalsecret'])) { $secret = $photoInfo['originalsecret']; $format = isset($photoInfo['originalformat']) ? $photoInfo['originalformat'] : 'jpg'; } return "https://live.staticflickr.com/{$server}/{$photoId}_{$secret}{$suffix}.{$format}"; } /** * Decode Flickr's base58 short URL to photo ID * * @param string $encoded Base58 encoded string * @return string Photo ID */ private function decodeBase58($encoded) { $alphabet = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'; $base = strlen($alphabet); $decoded = '0'; for ($i = 0; $i < strlen($encoded); $i++) { $pos = strpos($alphabet, $encoded[$i]); $decoded = bcmul($decoded, (string)$base); $decoded = bcadd($decoded, (string)$pos); } return $decoded; } /** * Get available sizes * * @return array Size names */ public function getAvailableSizes() { return array_keys(self::SIZES); } }