Completed
Push — master ( 0e0bf2...e5f058 )
by Benjamin
03:52
created

MediaProvider::fetchFromCache()   C

Complexity

Conditions 7
Paths 11

Size

Total Lines 29
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 29
rs 6.7272
cc 7
eloc 22
nc 11
nop 1
1
<?php
2
3
namespace Alpixel\Bundle\MediaBundle\DataFixtures\ORM;
4
5
use Alpixel\Bundle\MediaBundle\Services\MediaManager;
6
use Faker\Provider\Base as BaseProvider;
7
use Symfony\Component\Filesystem\Filesystem;
8
use Symfony\Component\Finder\Finder;
9
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
10
use Symfony\Component\HttpFoundation\File\File;
11
12
class MediaProvider extends BaseProvider
13
{
14
    protected $mediaManager;
15
16
    public function __construct(MediaManager $mediaManager)
17
    {
18
        $this->mediaManager = $mediaManager;
19
    }
20
21
    /** @deprecated */
22
    public function randomMedia($width = null, $height = null, $type = 'color')
23
    {
24
        return $this->randomImage($width, $height, $type);
25
    }
26
27
    public function randomImage($width = null, $height = null, $type = 'color')
28
    {
29
        do {
30
            $dimensions = $this->fetchDimensions($width, $height);
31
            $file = $this->fetchFromCache($dimensions['w'] . '-' . $dimensions['h']);
32
            if ($file === null) {
33
                $file = $this->downloadMedia($this->generateUrl($dimensions, $type), 'jpg');
34
                $this->storeInCache($dimensions['w'] . '-' . $dimensions['h'], $file);
35
            }
36
        } while (!preg_match('@^image/@', $file->getMimeType()));
37
38
        $media = $this->mediaManager->upload($file);
39
40
        return $media;
41
    }
42
43
    public function randomFile($fileType)
44
    {
45
        $file = $this->fetchFromCache("file-" . $fileType);
46
        if ($file === null) {
47
            switch ($fileType) {
48
                case "pdf":
49
                default:
50
                    $file = $this->downloadMedia("https://symfony.com/pdf/Symfony_book_master.pdf", $fileType);
51
                    break;
52
            }
53
        }
54
        $this->storeInCache("file-" . $fileType, $file);
55
        $media = $this->mediaManager->upload($file);
56
57
        return $media;
58
    }
59
60
    protected function fetchDimensions($width = null, $height = null)
61
    {
62
        if ($width === null && $height !== null) {
63
            $width = round($height * 4 / 3);
64
        } elseif ($width !== null && $height === null) {
65
            $height = round($width * 3 / 4);
66
        } else {
67
            $aWidth = [800, 1200, 1600];
68
            $width = array_rand($aWidth, 1);
69
            $width = $aWidth[$width];
70
            $height = round($width * 3 / 4);
71
        }
72
73
        return ['w' => $width, 'h' => $height];
74
    }
75
76
    protected function generateUrl($dimensions, $type = 'color')
77
    {
78
        $url = 'http://loremflickr.com/';
79
80
        if ($type !== 'color') {
81
            $url .= 'g/';
82
        }
83
84
        $url .= $dimensions['w'] . '/' . $dimensions['h'];
85
86
        $category = ['abstract', 'city', 'nature', 'moutains'];
87
        $url .= '/' . $category[array_rand($category, 1)] . '/';
88
89
        return $url;
90
    }
91
92
    protected function downloadMedia($url, $ext)
93
    {
94
        $filepath = sys_get_temp_dir() . '/' . uniqid() . '.' . $ext;
95
        $ch = curl_init($url);
96
        $fp = fopen($filepath, 'wb');
97
        curl_setopt($ch, CURLOPT_FILE, $fp);
98
        curl_setopt($ch, CURLOPT_HEADER, 0);
99
        curl_exec($ch);
100
        curl_close($ch);
101
        fclose($fp);
102
103
        return new File($filepath, 'random');
0 ignored issues
show
Documentation introduced by
'random' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
104
    }
105
106
    protected function fetchFromCache($key)
0 ignored issues
show
Coding Style introduced by
fetchFromCache uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
107
    {
108
        $fs = new Filesystem();
109
        $cacheDir = $_SERVER['HOME'] . '/.symfony/media';
110
        if (!$fs->exists($cacheDir)) {
111
            $fs->mkdir($cacheDir, 0777);
112
        } else {
113
            $cacheDir .= '/' . $key;
114
            if (!$fs->exists($cacheDir)) {
115
                $fs->mkdir($cacheDir, 0777);
116
            } else {
117
                $finder = new Finder();
118
                $files = $finder->in($cacheDir . '/')->files();
119
                if (strrpos($key, "file-") !== false || $files->count() === 3) {
120
                    try {
121
                        $iterator = $finder->getIterator();
122
                        $iterator->rewind();
123
                        for ($i = 0; $i < rand(0, 2); $i++) {
124
                            $iterator->next();
125
                        }
126
                        $file = new File($iterator->current());
127
                        $fs->copy($file->getRealPath(), sys_get_temp_dir() . '/' . $file->getFilename());
128
129
                        return new File(sys_get_temp_dir() . '/' . $file->getFilename());
130
                    } catch(FileNotFoundException $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
131
                }
132
            }
133
        }
134
    }
135
136
    protected function storeInCache($key, File $file)
0 ignored issues
show
Coding Style introduced by
storeInCache uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
137
    {
138
        $fs = new Filesystem();
139
        $cacheDir = $_SERVER['HOME'] . '/.symfony/media/' . $key;
140
        if (!$fs->exists($cacheDir)) {
141
            $fs->mkdir($cacheDir, 0777);
142
        }
143
        $fs->copy($file->getRealPath(), $cacheDir . '/' . $file->getFilename());
144
    }
145
}
146