Passed
Push — master ( 247982...3826b4 )
by Jakub
06:20
created

TCollection::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Utils;
5
6
use Nette\Utils\Arrays;
7
8
/**
9
 * TCollection
10
 * Target class has to implement \ArrayAccess, \Countable, \IteratorAggregate interfaces
11
 *
12
 * @author Jakub Konečný
13
 */
14 1
trait TCollection {
15
  protected $items = [];
16
  /** @var string Type of items in the collection */
17
  protected $class;
18
  /** @var string|NULL */
19
  protected $uniqueProperty = NULL;
20
  /** @var bool */
21
  protected $locked = false;
22
  
23
  public function isLocked(): bool {
24 1
    return $this->locked;
25
  }
26
  
27
  public function lock(): void {
28 1
    $this->locked = true;
29 1
  }
30
  
31
  public function count(): int {
32 1
    return count($this->items);
33
  }
34
  
35
  public function getIterator(): \ArrayIterator {
36 1
    return new \ArrayIterator($this->items);
37
  }
38
  
39
  /**
40
   * @param int $index
41
   */
42
  public function offsetExists($index): bool {
43 1
    return $index >= 0 AND $index < count($this->items);
44
  }
45
  
46
  /**
47
   * @param int|NULL $index
48
   * @throws \OutOfRangeException
49
   */
50
  public function offsetGet($index) {
51 1
    if($index < 0 OR $index >= count($this->items)) {
52 1
      throw new \OutOfRangeException("Offset invalid or out of range.");
53
    }
54 1
    return $this->items[$index];
55
  }
56
  
57
  /**
58
   * @param object $newItem
59
   */
60
  protected function checkType($newItem): bool {
61 1
    return ($newItem instanceof $this->class);
62
  }
63
  
64
  /**
65
   * @param object $newItem
66
   */
67
  protected function checkUniqueness($newItem): bool {
68 1
    if(is_null($this->uniqueProperty)) {
69 1
      return true;
70
    }
71 1
    return Arrays::every($this->items, function($value) use($newItem) {
72 1
      return ($newItem->{$this->uniqueProperty} !== $value->{$this->uniqueProperty});
73 1
    });
74
  }
75
  
76
  /**
77
   * @param int|NULL $index
78
   * @param object $item
79
   * @throws \OutOfRangeException
80
   * @throws \InvalidArgumentException
81
   * @throws \RuntimeException
82
   */
83
  public function offsetSet($index, $item): void {
84 1
    if($this->locked) {
85 1
      throw new \RuntimeException("Cannot add items to locked collection.");
86 1
    } elseif(!$this->checkType($item)) {
87 1
      throw new \InvalidArgumentException("Argument must be of $this->class type.");
88 1
    } elseif(!$this->checkUniqueness($item)) {
89 1
      $property = $this->uniqueProperty;
90 1
      throw new \RuntimeException("Duplicate $property {$item->$property}.");
91
    }
92 1
    if($index === NULL) {
93 1
      $this->items[] = & $item;
94 1
    } elseif($index < 0 OR $index >= count($this->items)) {
95 1
      throw new \OutOfRangeException("Offset invalid or out of range.");
96
    } else {
97 1
      $this->items[$index] = & $item;
98
    }
99 1
  }
100
  
101
  /**
102
   * @param int $index
103
   * @throws \OutOfRangeException
104
   */
105
  public function offsetUnset($index): void {
106 1
    if($this->locked) {
107 1
      throw new \RuntimeException("Cannot remove items from locked collection.");
108 1
    } elseif($index < 0 OR $index >= count($this->items)) {
109 1
      throw new \OutOfRangeException("Offset invalid or out of range.");
110
    }
111 1
    array_splice($this->items, $index, 1);
112 1
  }
113
}
114
?>