Completed
Push — master ( d21053...c59b30 )
by
unknown
08:11
created

TidypicsAlbum   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 384
Duplicated Lines 6.25 %

Coupling/Cohesion

Components 3
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 24
loc 384
ccs 0
cts 215
cp 0
rs 8.64
c 0
b 0
f 0
wmc 47
lcom 3
cbo 3

22 Methods

Rating   Name   Duplication   Size   Complexity  
A initializeAttributes() 0 5 1
A __construct() 0 3 1
A save() 0 18 4
A delete() 0 7 1
A getTitle() 0 3 1
A getURL() 0 5 1
A getImages() 0 14 3
A viewImages() 0 27 3
A getCoverImage() 0 3 1
A getCoverImageGuid() 0 15 3
A setCoverImageGuid() 0 8 2
A getSize() 0 3 1
A getImageList() 0 25 3
A setImageList() 0 12 3
A prependImageList() 0 5 1
A getPreviousImage() 12 12 3
A getNextImage() 12 12 3
A getIndex() 0 3 1
A removeImage() 0 12 2
A shouldNotify() 0 3 1
A deleteImages() 0 22 4
A deleteAlbumDir() 0 32 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like TidypicsAlbum often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TidypicsAlbum, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Tidypics Album class
4
 *
5
 * @package TidypicsAlbum
6
 * @author Cash Costello
7
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License v2
8
 */
9
10
11
class TidypicsAlbum extends ElggObject {
12
	/**
13
	 * Sets the internal attributes
14
	 */
15
	protected function initializeAttributes() {
16
		parent::initializeAttributes();
17
18
		$this->attributes['subtype'] = "album";
19
	}
20
21
	/**
22
	 * Constructor
23
	 * @param mixed $guid
24
	 */
25
	public function __construct($guid = null) {
26
		parent::__construct($guid);
27
	}
28
29
	/**
30
	 * Save an album
31
	 *
32
	 * @return bool
33
	 */
34
	public function save() {
35
36
		if (!isset($this->new_album)) {
37
			$this->new_album = true;
38
		}
39
40
		if (!isset($this->last_notified)) {
41
			$this->last_notified = 0;
42
		}
43
44
		if (!parent::save()) {
45
			return false;
46
		}
47
48
		mkdir(tp_get_img_dir($this->guid), 0755, true);
49
50
		return true;
51
	}
52
53
	/**
54
	 * Delete album
55
	 *
56
	 * @return bool
57
	 */
58
	public function delete() {
59
60
		$this->deleteImages();
61
		$this->deleteAlbumDir();
62
63
		return parent::delete();
64
	}
65
66
	/**
67
	 * Get the title of the photo album
68
	 *
69
	 * @return string
70
	 */
71
	public function getTitle() {
72
		return $this->title;
73
	}
74
75
	/**
76
	 * Get the URL for this album
77
	 *
78
	 * @return string
79
	 */
80
	public function getURL() {
81
		$title = elgg_get_friendly_title($this->getTitle());
82
		$url = "photos/album/$this->guid/$title";
83
		return elgg_normalize_url($url);
84
	}
85
86
	/**
87
	 * Get an array of image objects
88
	 *
89
	 * @param int $limit
90
	 * @param int $offset
91
	 * @return array
92
	 */
93
	public function getImages($limit, $offset = 0) {
94
		$imageList = $this->getImageList();
95
		if ($offset > count($imageList)) {
96
			return array();
97
		}
98
99
		$imageList = array_slice($imageList, $offset, $limit);
100
101
		$images = array();
102
		foreach ($imageList as $guid) {
103
			$images[] = get_entity($guid);
104
		}
105
		return $images;
106
	}
107
108
	/**
109
	 * View a list of images
110
	 *
111
	 * @param array $options Options to pass to elgg_view_entity_list()
112
	 * @return string
113
	 */
114
	public function viewImages(array $options = array()) {
115
		$count = $this->getSize();
116
117
		if ($count == 0) {
118
			return '';
119
		}
120
121
		$defaults = array(
122
			'count' => $count,
123
			'limit' => (int)get_input('limit', 16),
124
			'offset' => (int)get_input('offset', 0),
125
			'full_view' => false,
126
			'list_type' => 'gallery',
127
			'list_type_toggle' => false,
128
			'pagination' => true,
129
			'gallery_class' => 'tidypics-gallery',
130
		);
131
132
		$options = array_merge($defaults, (array) $options);
133
		$images = $this->getImages($options['limit'], $options['offset']);
134
135
		if (count($images) == 0) {
136
			return '';
137
		}
138
139
		return elgg_view_entity_list($images, $options);
140
	}
141
142
	/**
143
	 * Returns the cover image entity
144
	 * @return TidypicsImage
145
	 */
146
	public function getCoverImage() {
147
		return get_entity($this->getCoverImageGuid());
148
	}
149
150
	/**
151
	 * Get the GUID of the album cover
152
	 *
153
	 * @return int
154
	 */
155
	public function getCoverImageGuid() {
156
		if ($this->getSize() == 0) {
157
			return 0;
158
		}
159
160
		$guid = $this->cover;
161
		$imageList = $this->getImageList();
162
		if (!in_array($guid, $imageList)) {
163
			// select random photo to be cover
164
			$index = array_rand($imageList, 1);
165
			$guid = $imageList[$index];
166
			$this->cover = $guid;
167
		}
168
		return $guid;
169
	}
170
171
	/**
172
	 * Set the GUID for the album cover
173
	 *
174
	 * @param int $guid
175
	 * @return bool
176
	 */
177
	public function setCoverImageGuid($guid) {
178
		$imageList = $this->getImageList();
179
		if (!in_array($guid, $imageList)) {
180
			return false;
181
		}
182
		$this->cover = $guid;
183
		return true;
184
	}
185
186
	/**
187
	 * Get the number of photos in the album
188
	 *
189
	 * @return int
190
	 */
191
	public function getSize() {
192
		return count($this->getImageList());
193
	}
194
195
	/**
196
	 * Returns an order list of image guids
197
	 *
198
	 * @return array
199
	 */
200
	public function getImageList() {
201
		$listString = $this->orderedImages;
202
		if (!$listString) {
203
			return array();
204
		}
205
		$list = unserialize($listString);
206
207
		// if empty don't need to check the permissions.
208
		if (!$list) {
209
			return array();
210
		}
211
212
		// check access levels
213
		$guidsString = implode(',', $list);
214
215
		$options = array(
216
			'wheres' => array("e.guid IN ($guidsString)"),
217
			'order_by' => "FIELD(e.guid, $guidsString)",
218
			'callback' => 'tp_guid_callback',
219
			'limit' => ELGG_ENTITIES_NO_VALUE
220
		);
221
222
		$list = elgg_get_entities($options);
223
		return $list;
224
	}
225
226
	/**
227
	 * Sets the album image order
228
	 *
229
	 * @param array $list An indexed array of image guids
230
	 * @return bool
231
	 */
232
	public function setImageList($list) {
233
		// validate data
234
		foreach ($list as $guid) {
235
			if (!filter_var($guid, FILTER_VALIDATE_INT)) {
236
				return false;
237
			}
238
		}
239
240
		$listString = serialize($list);
241
		$this->orderedImages = $listString;
242
		return true;
243
	}
244
245
	/**
246
	 * Add new images to the front of the image list
247
	 *
248
	 * @param array $list An indexed array of image guids
249
	 * @return bool
250
	 */
251
	public function prependImageList($list) {
252
		$currentList = $this->getImageList();
253
		$list = array_merge($list, $currentList);
254
		return $this->setImageList($list);
255
	}
256
257
	/**
258
	 * Get the previous image in the album. Wraps around to the last image if given the first.
259
	 *
260
	 * @param int $guid GUID of the current image
261
	 * @return TidypicsImage
262
	 */
263 View Code Duplication
	public function getPreviousImage($guid) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
		$imageList = $this->getImageList();
265
		$key = array_search($guid, $imageList);
266
		if ($key === FALSE) {
267
			return null;
268
		}
269
		$key--;
270
		if ($key < 0) {
271
			return get_entity(end($imageList));
272
		}
273
		return get_entity($imageList[$key]);
274
	}
275
276
	/**
277
	 * Get the next image in the album. Wraps around to the first image if given the last.
278
	 *
279
	 * @param int $guid GUID of the current image
280
	 * @return TidypicsImage
281
	 */
282 View Code Duplication
	public function getNextImage($guid) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
283
		$imageList = $this->getImageList();
284
		$key = array_search($guid, $imageList);
285
		if ($key === FALSE) {
286
			return null;
287
		}
288
		$key++;
289
		if ($key >= count($imageList)) {
290
			return get_entity($imageList[0]);
291
		}
292
		return get_entity($imageList[$key]);
293
	}
294
295
	/**
296
	 * Get the index into the album for a particular image
297
	 *
298
	 * @param int $guid GUID of the image
299
	 * @return int
300
	 */
301
	public function getIndex($guid) {
302
		return array_search($guid, $this->getImageList()) + 1;
303
	}
304
305
	/**
306
	 * Remove an image from the album list
307
	 *
308
	 * @param int $imageGuid
309
	 * @return bool
310
	 */
311
	public function removeImage($imageGuid)  {
312
		$imageList = $this->getImageList();
313
		$key = array_search($imageGuid, $imageList);
314
		if ($key === false) {
315
			return false;
316
		}
317
318
		unset($imageList[$key]);
319
		$this->setImageList($imageList);
320
321
		return true;
322
	}
323
324
	/**
325
	 * Has enough time elapsed between the last_notified and notify_interval setting?
326
	 *
327
	 * @return bool
328
	 */
329
	public function shouldNotify() {
330
		return time() - $this->last_notified > elgg_get_plugin_setting('notify_interval', 'tidypics');
331
	}
332
333
	/**
334
	 * Delete all the images in this album
335
	 */
336
	protected function deleteImages() {
337
		$images_count = elgg_get_entities(array(
338
			"type" => "object",
339
			"subtype" => "image",
340
			"container_guid" => $this->guid,
341
			"count" => true,
342
		));
343
		if ($images_count > 0) {
344
			$images = new ElggBatch('elgg_get_entities', array(
345
				"type" => "object",
346
				"subtype" => "image",
347
				"container_guid" => $this->guid,
348
				"limit" => ELGG_ENTITIES_NO_VALUE,
349
			));
350
			$images->setIncrementOffset(false);
351
			foreach ($images as $image) {
352
				if ($image) {
353
					$image->delete();
354
				}
355
			}
356
		}
357
	}
358
359
	/**
360
	 * Delete the album directory on disk
361
	 */
362
	protected function deleteAlbumDir() {
363
		$tmpfile = new ElggFile();
364
		$tmpfile->setFilename('image/' . $this->guid . '/._tmp_del_tidypics_album_');
365
		$tmpfile->subtype = 'image';
366
		$tmpfile->owner_guid = $this->owner_guid;
367
		$tmpfile->container_guid = $this->guid;
368
		$tmpfile->open("write");
369
		$tmpfile->write('');
370
		$tmpfile->close();
371
		$tmpfile->save();
372
		$albumdir = eregi_replace('/._tmp_del_tidypics_album_', '', $tmpfile->getFilenameOnFilestore());
373
		$tmpfile->delete();
374
375
                // sanity check: must be a directory
376
                if (!$handle = opendir($albumdir)) {
377
                        return false;
378
                }
379
380
                // loop through all files that might still remain undeleted in this directory and delete them
381
                // note: this does not delete the corresponding image entities from the database
382
                while (($file = readdir($handle)) !== false) {
383
                        if (in_array($file, array('.', '..'))) {
384
                                continue;
385
                        }
386
                        $path = "$albumdir/$file";
387
                        unlink($path);
388
                }
389
390
                // remove empty directory
391
                closedir($handle);
392
                return rmdir($albumdir);
393
	}
394
}
395