Completed
Pull Request — master (#191)
by Emanuele
03:10
created

AdImage::read()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 23
rs 8.7972
cc 4
eloc 14
nc 4
nop 2
1
<?php
2
/**
3
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
25
namespace FacebookAds\Object;
26
27
use FacebookAds\Api;
28
use FacebookAds\Cursor;
29
use FacebookAds\Http\RequestInterface;
30
use FacebookAds\Object\Fields\AdImageFields;
31
use FacebookAds\Object\Traits\CannotUpdate;
32
use FacebookAds\Object\Traits\FieldValidation;
33
34
class AdImage extends AbstractCrudObject
35
{
36
    use FieldValidation;
37
    use CannotUpdate;
38
39
    /**
40
     * Uploads images from a zip file and returns a cursor of results
41
     *
42
     * @param string $file_path
43
     * @param string $account_id
44
     * @param array $params
45
     * @param Api $api
46
     * @return array
47
     */
48
    public static function createFromZip(
49
        $file_path,
50
        $account_id,
51
        array $params = array(),
52
        Api $api = null
53
    ) {
54
        $image = new AdImage(null, $account_id, $api);
55
        $image->{AdImageFields::FILENAME} = $file_path;
56
        return $image->arrayFromZip($params);
57
    }
58
59
    /**
60
     * @return string
61
     */
62
    protected function getEndpoint()
63
    {
64
        return 'adimages';
65
    }
66
67
    /**
68
     * @return AdImageFields
69
     */
70
    public static function getFieldsEnum()
71
    {
72
        return AdImageFields::getInstance();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \FacebookAds\Obje...eFields::getInstance(); (FacebookAds\Object\Fields\AdImageFields) is incompatible with the return type of the parent method FacebookAds\Object\AbstractObject::getFieldsEnum of type FacebookAds\Enum\EmptyEnum.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
73
    }
74
75
    /**
76
     * @return string
77
     */
78
    protected function getNodePath()
79
    {
80
        return '/'.$this->assureParentId().'/'.$this->getEndpoint();
81
    }
82
83
    /**
84
     * Create function for the object.
85
     *
86
     * @param array $params Additional parameters to include in the request
87
     * @return $this
88
     * @throws \Exception
89
     * @throws \RuntimeException
90
     */
91
    public function create(array $params = array())
92
    {
93
        if ($this->data[static::FIELD_ID]) {
94
            throw new \Exception("Object has already an ID");
95
        }
96
97
        if ($this->isZipFile($this->data[AdImageFields::FILENAME])) {
98
            throw new \RuntimeException("use AdImage::createFromZip to create zip files");
99
        }
100
101
        $data = $this->exportData();
102
        $filename = $data[AdImageFields::FILENAME];
103
        unset($data[AdImageFields::FILENAME]);
104
        $params = array_merge($data, $params);
105
106
        $request = $this->getApi()->prepareRequest(
107
            '/'.$this->assureParentId().'/'.$this->getEndpoint(),
108
            RequestInterface::METHOD_POST,
109
            $params
110
        );
111
112
        $request->getFileParams()->offsetSet(AdImageFields::FILENAME, $filename);
113
        $response = $this->getApi()->executeRequest($request);
114
115
        $this->clearHistory();
116
        $data = $response->getContent()['images']
117
            [basename($this->{AdImageFields::FILENAME})];
118
119
        $this->data[AdImageFields::HASH] = $data[AdImageFields::HASH];
120
121
        $this->data[static::FIELD_ID]
122
            = substr($this->getParentId(), 4).':'.$this->data[AdImageFields::HASH];
123
124
        return $this;
125
    }
126
127
    /**
128
     * Read object data from the graph
129
     *
130
     * @param string[] $fields Fields to request
131
     * @param array $params Additional request parameters
132
     * @return $this
133
     */
134
    public function read(array $fields = array(), array $params = array())
135
    {
136
        $fields = implode(',', $fields ?: static::getDefaultReadFields());
137
        if ($fields) {
138
            $params['fields'] = $fields;
139
        }
140
        $params['hashes'] = array(explode(':', $this->assureId())[1]);
141
142
        $response = $this->getApi()->call(
143
            $this->getNodePath(),
144
            RequestInterface::METHOD_GET,
145
            $params
146
        );
147
148
        $data = $response->getContent()['data'];
149
        if ($data) {
150
            $this->setDataWithoutValidation((array) $data[0]);
151
        }
152
153
        $this->clearHistory();
154
155
        return $this;
156
    }
157
158
    /**
159
     * Delete this object from the graph
160
     *
161
     * @param array $params
162
     * @return void
163
     * @throws \Exception
164
     */
165
    public function delete(array $params = array())
166
    {
167
        if (!$this->data[AdImageFields::HASH]) {
168
            throw new \Exception("AdImage hash is required to delete");
169
        }
170
171
        $params
172
            = array_merge($params, array('hash' => $this->data[AdImageFields::HASH]));
173
174
        parent::delete($params);
175
    }
176
177
    /**
178
     * Uploads images from a zip file and returns a cursor of results
179
     *
180
     * @param array $params
181
     * @return array
182
     * @throws \RuntimeException
183
     */
184
    protected function arrayFromZip($params = array())
185
    {
186
        if (!$this->isZipFile($this->data[AdImageFields::FILENAME])) {
187
            throw new \RuntimeException($this->data[AdImageFields::FILENAME]." doesn't resolve to a zip file");
188
        }
189
190
        $data = $this->exportData();
191
        $filename = $data[AdImageFields::FILENAME];
192
        unset($data[AdImageFields::FILENAME]);
193
        $params = array_merge($data, $params);
194
195
        $request = $this->getApi()->prepareRequest(
196
            '/'.$this->assureParentId().'/'.$this->getEndpoint(),
197
            RequestInterface::METHOD_POST,
198
            $params
199
        );
200
201
        $request->getFileParams()->offsetSet(AdImageFields::FILENAME, $filename);
202
        $response = $this->getApi()->executeRequest($request);
203
204
        $result = array();
205
        foreach ($response->getContent()['images'] as $image) {
206
            $adimage = new AdImage(
207
                substr($this->getParentId(), 4).':'.$image[AdImageFields::HASH],
208
                $this->getParentId(),
209
                $this->getApi()
210
            );
211
212
            $adimage->{AdImageFields::HASH} = $image[AdImageFields::HASH];
213
214
            $result[] = $adimage;
215
        }
216
217
        return $result;
218
    }
219
220
    /**
221
     * Checks if a given path is a zip file
222
     *
223
     * @param string $file_path
224
     * @return bool
225
     */
226
    protected function isZipFile($file_path)
227
    {
228
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
229
        $file_mime_type = finfo_file($finfo, $file_path);
230
        return $file_mime_type == 'application/zip' ||
231
            $file_mime_type == 'multipart/x-zip';
232
    }
233
}
234