sonata-project /
SonataMediaBundle
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | /* |
||
| 6 | * This file is part of the Sonata Project package. |
||
| 7 | * |
||
| 8 | * (c) Thomas Rabaix <[email protected]> |
||
| 9 | * |
||
| 10 | * For the full copyright and license information, please view the LICENSE |
||
| 11 | * file that was distributed with this source code. |
||
| 12 | */ |
||
| 13 | |||
| 14 | namespace Sonata\MediaBundle\CDN; |
||
| 15 | |||
| 16 | use Aws\CloudFront\CloudFrontClient; |
||
| 17 | use Aws\CloudFront\Exception\CloudFrontException; |
||
| 18 | |||
| 19 | /** |
||
| 20 | * From http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html. |
||
| 21 | * |
||
| 22 | * Invalidating Objects (Web Distributions Only) |
||
| 23 | * If you need to remove an object from CloudFront edge-server caches before it |
||
| 24 | * expires, you can do one of the following: |
||
| 25 | * Invalidate the object. The next time a viewer requests the object, CloudFront |
||
| 26 | * returns to the origin to fetch the latest version of the object. |
||
| 27 | * Use object versioning to serve a different version of the object that has a |
||
| 28 | * different name. For more information, see Updating Existing Objects Using |
||
| 29 | * Versioned Object Names. |
||
| 30 | * Important: |
||
| 31 | * You can invalidate most types of objects that are served by a web |
||
| 32 | * distribution, but you cannot invalidate media files in the Microsoft Smooth |
||
| 33 | * Streaming format when you have enabled Smooth Streaming for the corresponding |
||
| 34 | * cache behavior. In addition, you cannot invalidate objects that are served by |
||
| 35 | * an RTMP distribution. You can invalidate a specified number of objects each |
||
| 36 | * month for free. Above that limit, you pay a fee for each object that you |
||
| 37 | * invalidate. For example, to invalidate a directory and all of the files in |
||
| 38 | * the directory, you must invalidate the directory and each file individually. |
||
| 39 | * If you need to invalidate a lot of files, it might be easier and less |
||
| 40 | * expensive to create a new distribution and change your object paths to refer |
||
| 41 | * to the new distribution. For more information about the charges for |
||
| 42 | * invalidation, see Paying for Object Invalidation. |
||
| 43 | * |
||
| 44 | * @final since sonata-project/media-bundle 3.21.0 |
||
| 45 | * |
||
| 46 | * @uses \CloudFrontClient for stablish connection with CloudFront service |
||
| 47 | * |
||
| 48 | * @see http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.htmlInvalidating Objects (Web Distributions Only) |
||
| 49 | * |
||
| 50 | * @author Javier Spagnoletti <[email protected]> |
||
| 51 | */ |
||
| 52 | class CloudFront implements CDNInterface |
||
| 53 | { |
||
| 54 | /** |
||
| 55 | * @var string |
||
| 56 | */ |
||
| 57 | protected $path; |
||
| 58 | |||
| 59 | /** |
||
| 60 | * @var string |
||
| 61 | */ |
||
| 62 | protected $key; |
||
| 63 | |||
| 64 | /** |
||
| 65 | * @var string |
||
| 66 | */ |
||
| 67 | protected $secret; |
||
| 68 | |||
| 69 | /** |
||
| 70 | * @var string |
||
| 71 | */ |
||
| 72 | protected $distributionId; |
||
| 73 | |||
| 74 | /** |
||
| 75 | * @var CloudFrontClient |
||
| 76 | */ |
||
| 77 | protected $client; |
||
| 78 | |||
| 79 | /** |
||
| 80 | * @param string $path |
||
| 81 | * @param string $key |
||
| 82 | * @param string $secret |
||
| 83 | * @param string $distributionId |
||
| 84 | */ |
||
| 85 | public function __construct($path, $key, $secret, $distributionId) |
||
| 86 | { |
||
| 87 | $this->path = $path; |
||
| 88 | $this->key = $key; |
||
| 89 | $this->secret = $secret; |
||
| 90 | $this->distributionId = $distributionId; |
||
| 91 | } |
||
| 92 | |||
| 93 | public function getPath($relativePath, $isFlushable = false) |
||
| 94 | { |
||
| 95 | return sprintf('%s/%s', rtrim($this->path, '/'), ltrim($relativePath, '/')); |
||
| 96 | } |
||
| 97 | |||
| 98 | public function flushByString($string) |
||
| 99 | { |
||
| 100 | return $this->flushPaths([$string]); |
||
| 101 | } |
||
| 102 | |||
| 103 | public function flush($string) |
||
| 104 | { |
||
| 105 | return $this->flushPaths([$string]); |
||
| 106 | } |
||
| 107 | |||
| 108 | /** |
||
| 109 | * {@inheritdoc} |
||
| 110 | * |
||
| 111 | * @see http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.CloudFront.CloudFrontClient.html#_createInvalidation |
||
| 112 | */ |
||
| 113 | public function flushPaths(array $paths) |
||
| 114 | { |
||
| 115 | if (empty($paths)) { |
||
| 116 | throw new \RuntimeException('Unable to flush : expected at least one path'); |
||
| 117 | } |
||
| 118 | // Normalizes paths due possible typos since all the CloudFront's |
||
| 119 | // objects starts with a leading slash |
||
| 120 | $normalizedPaths = array_map(static function ($path) { |
||
| 121 | return '/'.ltrim($path, '/'); |
||
| 122 | }, $paths); |
||
| 123 | |||
| 124 | try { |
||
| 125 | $result = $this->getClient()->createInvalidation([ |
||
| 126 | 'DistributionId' => $this->distributionId, |
||
| 127 | 'Paths' => [ |
||
| 128 | 'Quantity' => \count($normalizedPaths), |
||
| 129 | 'Items' => $normalizedPaths, |
||
| 130 | ], |
||
| 131 | 'CallerReference' => $this->getCallerReference($normalizedPaths), |
||
| 132 | ]); |
||
| 133 | |||
| 134 | if (!\in_array($status = $result->get('Status'), ['Completed', 'InProgress'], true)) { |
||
| 135 | throw new \RuntimeException('Unable to flush : '.$status); |
||
| 136 | } |
||
| 137 | |||
| 138 | return $result->get('Id'); |
||
| 139 | } catch (CloudFrontException $ex) { |
||
| 140 | throw new \RuntimeException('Unable to flush : '.$ex->getMessage()); |
||
| 141 | } |
||
| 142 | } |
||
| 143 | |||
| 144 | /** |
||
| 145 | * For testing only. |
||
| 146 | */ |
||
| 147 | public function setClient(CloudFrontClient $client): void |
||
| 148 | { |
||
| 149 | $this->client = $client; |
||
| 150 | } |
||
| 151 | |||
| 152 | public function getFlushStatus($identifier) |
||
| 153 | { |
||
| 154 | try { |
||
| 155 | $result = $this->getClient()->getInvalidation([ |
||
| 156 | 'DistributionId' => $this->distributionId, |
||
| 157 | 'Id' => $identifier, |
||
| 158 | ]); |
||
| 159 | |||
| 160 | return array_search($result->get('Status'), self::getStatusList(), true); |
||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||
| 161 | } catch (CloudFrontException $ex) { |
||
| 162 | throw new \RuntimeException('Unable to retrieve flush status : '.$ex->getMessage()); |
||
| 163 | } |
||
| 164 | } |
||
| 165 | |||
| 166 | /** |
||
| 167 | * @static |
||
| 168 | * |
||
| 169 | * @return string[] |
||
| 170 | */ |
||
| 171 | public static function getStatusList() |
||
| 172 | { |
||
| 173 | // @todo: check for a complete list of available CloudFront statuses |
||
| 174 | return [ |
||
| 175 | self::STATUS_OK => 'Completed', |
||
| 176 | self::STATUS_TO_SEND => 'STATUS_TO_SEND', |
||
| 177 | self::STATUS_TO_FLUSH => 'STATUS_TO_FLUSH', |
||
| 178 | self::STATUS_ERROR => 'STATUS_ERROR', |
||
| 179 | self::STATUS_WAITING => 'InProgress', |
||
| 180 | ]; |
||
| 181 | } |
||
| 182 | |||
| 183 | /** |
||
| 184 | * Generates a valid caller reference from given paths regardless its order. |
||
| 185 | * |
||
| 186 | * @return string a md5 representation |
||
| 187 | */ |
||
| 188 | protected function getCallerReference(array $paths) |
||
| 189 | { |
||
| 190 | sort($paths); |
||
| 191 | |||
| 192 | return md5(implode(',', $paths)); |
||
| 193 | } |
||
| 194 | |||
| 195 | private function getClient(): CloudFrontClient |
||
| 196 | { |
||
| 197 | if (!$this->client) { |
||
| 198 | $this->client = CloudFrontClient::factory([ |
||
| 199 | 'key' => $this->key, |
||
| 200 | 'secret' => $this->secret, |
||
| 201 | ]); |
||
| 202 | } |
||
| 203 | |||
| 204 | return $this->client; |
||
| 205 | } |
||
| 206 | } |
||
| 207 |