Completed
Push — master ( 33d1a8...2dd810 )
by Benjamin
02:30
created

MediaProvider   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 7
Bugs 2 Features 1
Metric Value
wmc 19
c 7
b 2
f 1
lcom 1
cbo 4
dl 0
loc 109
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A randomMedia() 0 15 3
B fetchDimensions() 0 14 5
A generateUrl() 0 15 2
A downloadMedia() 0 13 1
B fetchFromCache() 0 27 5
A storeInCache() 0 9 2
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\File;
10
11
class MediaProvider extends BaseProvider
12
{
13
    protected $mediaManager;
14
15
    public function __construct(MediaManager $mediaManager)
16
    {
17
        $this->mediaManager = $mediaManager;
18
    }
19
20
    public function randomMedia($width = null, $height = null, $type = 'color')
21
    {
22
        do {
23
            $dimensions = $this->fetchDimensions($width, $height);
24
            $file = $this->fetchFromCache($dimensions);
25
            if ($file === null) {
26
                $file = $this->downloadMedia($this->generateUrl($dimensions, $type));
27
                $this->storeInCache($dimensions, $file);
28
            }
29
        } while (!preg_match('@^image/@', $file->getMimeType()));
30
31
        $media = $this->mediaManager->upload($file);
32
33
        return $media;
34
    }
35
36
    protected function fetchDimensions($width = null, $height = null)
37
    {
38
        if ($width === null && $height !== null) {
39
            $width = round($height * 4 / 3);
40
        } elseif ($width !== null && $height === null) {
41
            $height = round($width * 3 / 4);
42
        } else {
43
            $aWidth = [800, 1200, 1600];
44
            $width = array_rand($aWidth, 1);
45
            $width = $aWidth[$width];
46
            $height = round($width * 3 / 4);
47
        }
48
        return ['w' => $width, 'h' => $height];
49
    }
50
51
    protected function generateUrl($dimensions, $type = 'color')
52
    {
53
        $url = 'http://loremflickr.com/';
54
55
        if ($type !== 'color') {
56
            $url .= 'g/';
57
        }
58
59
        $url .= $dimensions['w'] . '/' . $dimensions['h'];
60
61
        $category = ['abstract', 'city', 'nature', 'moutains'];
62
        $url .= '/' . $category[array_rand($category, 1)] . '/';
63
64
        return $url;
65
    }
66
67
    protected function downloadMedia($url)
68
    {
69
        $filepath = sys_get_temp_dir() . '/' . uniqid() . '.jpg';
70
        $ch = curl_init($url);
71
        $fp = fopen($filepath, 'wb');
72
        curl_setopt($ch, CURLOPT_FILE, $fp);
73
        curl_setopt($ch, CURLOPT_HEADER, 0);
74
        curl_exec($ch);
75
        curl_close($ch);
76
        fclose($fp);
77
78
        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...
79
    }
80
81
    protected function fetchFromCache($dimensions)
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...
82
    {
83
        $fs = new Filesystem();
84
        $cacheDir = $_SERVER['HOME'] . '/.symfony/media';
85
        if (!$fs->exists($cacheDir)) {
86
            $fs->mkdir($cacheDir, 0777);
87
        } else {
88
            $cacheDir .= '/' . $dimensions['w'] . '-' . $dimensions['h'];
89
            if (!$fs->exists($cacheDir)) {
90
                $fs->mkdir($cacheDir, 0777);
91
            } else {
92
                $finder = new Finder();
93
                $files = $finder->in($cacheDir . '/')->files();
94
                if ($files->count() === 3) {
95
                    $iterator = $finder->getIterator();
96
                    $iterator->rewind();
97
                    for ($i = 0; $i < rand(0, 2); $i++) {
98
                        $iterator->next();
99
                    }
100
                    $file = new File($iterator->current());
101
                    $fs->copy($file->getRealPath(), sys_get_temp_dir().'/'.$file->getFilename());
102
                    return new File(sys_get_temp_dir().'/'.$file->getFilename());
103
                }
104
            }
105
        }
106
        return null;
107
    }
108
109
    protected function storeInCache($dimensions, 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...
110
    {
111
        $fs = new Filesystem();
112
        $cacheDir = $_SERVER['HOME'] . '/.symfony/media/' . $dimensions['w'] . '-' . $dimensions['h'];
113
        if (!$fs->exists($cacheDir)) {
114
            $fs->mkdir($cacheDir, 0777);
115
        }
116
        $fs->copy($file->getRealPath(), $cacheDir . '/' . $file->getFilename());
117
    }
118
119
}
120