1 <?php
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
22
23 define('PHPMORPHY_STORAGE_FILE', 'file');
24 define('PHPMORPHY_STORAGE_MEM', 'mem');
25 define('PHPMORPHY_STORAGE_SHM', 'shm');
26
27 abstract class phpMorphy_Storage {
28 protected
29 $file_name,
30 $resource;
31
32 function __construct($fileName) {
33 $this->file_name = $fileName;
34 $this->resource = $this->open($fileName);
35 }
36
37 function getFileName() { return $this->file_name; }
38 function getResource() { return $this->resource; }
39 function getTypeAsString() { return $this->getType(); }
40 function read($offset, $len, $exactLength = true) {
41 if($offset >= $this->getFileSize()) {
42 throw new phpMorphy_Exception("Can`t read $len bytes beyond end of '" . $this->getFileName() . "' file, offset = $offset, file_size = " . $this->getFileSize());
43 }
44
45 try {
46 $result = $this->readUnsafe($offset, $len);
47 } catch (Exception $e) {
48 throw new phpMorphy_Exception("Can`t read $len bytes at $offset offset, from '" . $this->getFileName() . "' file: " . $e->getMessage());
49 }
50
51 if($exactLength && $GLOBALS['__phpmorphy_strlen']($result) < $len) {
52 throw new phpMorphy_Exception("Can`t read $len bytes at $offset offset, from '" . $this->getFileName() . "' file");
53 }
54
55 return $result;
56 }
57
58 abstract function readUnsafe($offset, $len);
59 abstract function getFileSize();
60 abstract function getType();
61 abstract protected function open($fileName);
62 };
63
64 class phpMorphy_Storage_Proxy extends phpMorphy_Storage {
65 protected
66 $file_name,
67 $type,
68 $factory;
69
70 function __construct($type, $fileName, $factory) {
71 $this->file_name = $fileName;
72 $this->type = $type;
73 $this->factory = $factory;
74 }
75
76 function getFileName() { return $this->__obj->getFileName(); }
77 function getResource() { return $this->__obj->getResource(); }
78 function getFileSize() { return $this->__obj->getFileSize(); }
79 function getType() { return $this->__obj->getType(); }
80 function readUnsafe($offset, $len) { return $this->__obj->readUnsafe($offset, $len); }
81 protected function open($fileName) { return $this->__obj->open($fileName); }
82
83 function __get($propName) {
84 if($propName === '__obj') {
85 $this->__obj = $this->factory->open($this->type, $this->file_name, false);
86
87 unset($this->file_name);
88 unset($this->type);
89 unset($this->factory);
90
91 return $this->__obj;
92 }
93
94 throw new phpMorphy_Exception("Unknown '$propName' property");
95 }
96 }
97
98 class phpMorphy_Storage_File extends phpMorphy_Storage {
99 function getType() { return PHPMORPHY_STORAGE_FILE; }
100
101 function getFileSize() {
102 if(false === ($stat = fstat($this->resource))) {
103 throw new phpMorphy_Exception('Can`t invoke fstat for ' . $this->file_name . ' file');
104 }
105
106 return $stat['size'];
107 }
108
109 function readUnsafe($offset, $len) {
110 if(0 !== fseek($this->resource, $offset)) {
111 throw new phpMorphy_Exception("Can`t seek to $offset offset");
112 }
113
114 return fread($this->resource, $len);
115 }
116
117 function open($fileName) {
118 if(false === ($fh = fopen($fileName, 'rb'))) {
119 throw new phpMorphy_Exception("Can`t open $this->file_name file");
120 }
121
122 return $fh;
123 }
124 }
125
126 class phpMorphy_Storage_Mem extends phpMorphy_Storage {
127 function getType() { return PHPMORPHY_STORAGE_MEM; }
128
129 function getFileSize() {
130 return $GLOBALS['__phpmorphy_strlen']($this->resource);
131 }
132
133 function readUnsafe($offset, $len) {
134 return $GLOBALS['__phpmorphy_substr']($this->resource, $offset, $len);
135 }
136
137 function open($fileName) {
138 if(false === ($string = file_get_contents($fileName))) {
139 throw new phpMorphy_Exception("Can`t read $fileName file");
140 }
141
142 return $string;
143 }
144 }
145
146 class phpMorphy_Storage_Shm extends phpMorphy_Storage {
147 protected
148 $descriptor;
149
150 function __construct($fileName, $shmCache) {
151 $this->cache = $shmCache;
152
153 parent::__construct($fileName);
154 }
155
156 function getFileSize() {
157 return $this->descriptor->getFileSize();
158 }
159
160 function getType() { return PHPMORPHY_STORAGE_SHM; }
161
162 function readUnsafe($offset, $len) {
163 return shmop_read($this->resource['shm_id'], $this->resource['offset'] + $offset, $len);
164 }
165
166 function open($fileName) {
167 $this->descriptor = $this->cache->get($fileName);
168
169 return array(
170 'shm_id' => $this->descriptor->getShmId(),
171 'offset' => $this->descriptor->getOffset()
172 );
173 }
174 }
175
176 class phpMorphy_Storage_Factory {
177 protected
178 $shm_cache,
179 $shm_options;
180
181 function __construct($shmOptions = array()) {
182 $this->shm_options = $shmOptions;
183 }
184
185 function getShmCache() {
186 if(!isset($this->shm_cache)) {
187 $this->shm_cache = $this->createShmCache($this->shm_options);
188 }
189
190 return $this->shm_cache;
191 }
192
193 function open($type, $fileName, $lazy) {
194 switch($type) {
195 case PHPMORPHY_STORAGE_FILE:
196 case PHPMORPHY_STORAGE_MEM:
197 case PHPMORPHY_STORAGE_SHM: break;
198 default:
199 throw new phpMorphy_Exception("Invalid storage type $type specified");
200 }
201
202 if($lazy) {
203 return new phpMorphy_Storage_Proxy($type, $fileName, $this);
204 }
205
206 $clazz = 'phpMorphy_Storage_' . ucfirst($GLOBALS['__phpmorphy_strtolower']($type));
207
208 if($type != PHPMORPHY_STORAGE_SHM) {
209 return new $clazz($fileName);
210 } else {
211 return new $clazz($fileName, $this->getShmCache());
212 }
213 }
214
215 protected function createShmCache($options) {
216 require_once(PHPMORPHY_DIR . '/shm_utils.php');
217
218 return new phpMorphy_Shm_Cache($options, !empty($options['clear_on_create']));
219 }
220 }
221
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-