1: <?php
2: namespace NGS\Patterns;
3:
4: use NGS\Client\RestHttp;
5: use NGS\Client\Exception\NotFoundException;
6: use NGS\Utils;
7: use Memcached;
8:
9: 10: 11:
12: class Repository
13: {
14:
15: private $cache = array();
16:
17:
18: private $http;
19:
20: private $memcached;
21: private $prefix;
22: private static $instance;
23:
24: 25: 26:
27: public static function instance(Repository $repository=null)
28: {
29: if ($repository === null) {
30: return self::$instance ?: new Repository();
31: }
32: return self::$instance = $repository;
33: }
34:
35: public function __construct(RestHttp $http=null, Memcached $memcached=null, $prefix='')
36: {
37: $this->http = $http !== null ? $http : RestHttp::instance();
38:
39: if ($memcached) {
40: $this->memcached = $memcached;
41: }
42:
43: if ($prefix !== '' && !is_string($prefix)) {
44: throw new \InvalidArgumentException('Cache prefix name must be a string, invalid type was: "'.Utils::getType($prefix).'"');
45: }
46: $this->prefix = $prefix;
47: }
48:
49: public function invalidate($class, $uris)
50: {
51: if (!is_string($class)) {
52: throw new \InvalidArgumentException('Class name must be a string, invalid type was: "'.Utils::getType($class).'"');
53: }
54: if (isset($this->cache[$class])) {
55: $memcachedName = $this->prefix.$class.':';
56: if (is_array($uris)) {
57: $names = array();
58: foreach ($uris as $uri) {
59: unset($this->cache[$class][$uri]);
60: $names[] = $memcachedName.$uri;
61: }
62: if ($this->memcached) {
63:
64: if (method_exists($this->memcached, 'deleteMulti')) {
65: $this->memcached->deleteMulti($names);
66: }
67: else {
68: foreach ($names as $name) {
69: $this->memcached->delete($name);
70: }
71: }
72: }
73: }
74: else {
75: $name = $memcachedName.$uris;
76: unset($this->cache[$class][$uris]);
77: $this->memcached->delete($name);
78: }
79: }
80: }
81:
82: public function find($class, $uris)
83: {
84: if (!is_string($class)) {
85: throw new \InvalidArgumentException('Class name was not a string, invalid type was : "'.Utils::getType($uris).'"');
86: }
87: if (is_array($uris)) {
88: return $this->findMulti($class, $uris);
89: }
90: elseif(is_string($uris)) {
91: $items = $this->findMulti($class, array($uris));
92: if(!$items) {
93: throw new NotFoundException('Cannot find object "'.$class.'" with URI "'.$uris.'"');
94: }
95: return $items[0];
96: }
97: else {
98: throw new \InvalidArgumentException('Uris must be an array or string, invalid type was: "'.Utils::getType($uris).'"');
99: }
100: }
101:
102: private function findMulti($class, array $uris)
103: {
104: $results = array();
105: $missingUris = array();
106:
107: if(!isset($this->cache[$class])) {
108: $this->cache[$class] = array();
109: }
110: foreach ($uris as $uri) {
111: if (isset($this->cache[$class][$uri])) {
112: $results[$uri] = $this->cache[$class][$uri];
113: }
114: else {
115: $missingUris[$uri] = $uri;
116: }
117: }
118: if ($missingUris) {
119: $memcachedName = $this->prefix.$class.':';
120: if ($this->memcached) {
121: $names = array();
122: foreach ($missingUris as $uri) {
123: $names[] = $memcachedName.$uri;
124: }
125: $items = $this->memcached->getMulti($names);
126: if ($items) {
127: foreach($items as $item) {
128: $results[$item->URI] = $item;
129: $this->cache[$class][$item->URI] = $item;
130: unset($missingUris[$item->URI]);
131: }
132: }
133: }
134: if ($missingUris) {
135: $items = $class::find($missingUris);
136: $newItems = array();
137: foreach($items as $item) {
138: $results[$item->URI] = $item;
139: $this->cache[$class][$item->URI] = $item;
140: $newItems[$memcachedName.$item->URI] = $item;
141: }
142: if($this->memcached) {
143: $this->memcached->setMulti($newItems);
144: }
145: }
146: }
147:
148: $sortedResults = array();
149: foreach ($uris as $uri) {
150: if (isset($results[$uri])) {
151: $sortedResults[] = $results[$uri];
152: }
153: }
154: return $sortedResults;
155: }
156: }
157:
158: ?>
159: