Index: branches/FileBackend/phase3/includes/filerepo/AbstractFileStore.php |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * A particular data store may not support every operation. If it does not support |
| 6 | + * an operation that should return -1. It should not throw an exception as |
| 7 | + * the operation in question may be naively called from a loop that does not |
| 8 | + * check for support |
| 9 | + */ |
| 10 | +abstract class AbstractFileStore { |
| 11 | + |
| 12 | + abstract store( $params ) { |
| 13 | + return -1; |
| 14 | + } |
| 15 | + |
| 16 | + abstract relocate( $params ) { |
| 17 | + return -1; |
| 18 | + } |
| 19 | + |
| 20 | + abstract copy( $params ) { |
| 21 | + return -1; |
| 22 | + } |
| 23 | + |
| 24 | + abstract delete( $params ) { |
| 25 | + return -1; |
| 26 | + } |
| 27 | + |
| 28 | + abstract move( $params ) { |
| 29 | + return -1; |
| 30 | + } |
| 31 | + |
| 32 | + abstract concatinate( $params ) { |
| 33 | + return -1; |
| 34 | + } |
| 35 | + |
| 36 | + abstract fileExists( $params ) { |
| 37 | + return -1; |
| 38 | + } |
| 39 | + |
| 40 | + abstract getLocalCopy( $params ) { |
| 41 | + return -1; |
| 42 | + } |
| 43 | +} // end class |
\ No newline at end of file |
Property changes on: branches/FileBackend/phase3/includes/filerepo/AbstractFileStore.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 44 | + native |
Index: branches/FileBackend/phase3/includes/filerepo/dataStores/MemcachedDataStore.php |
— | — | @@ -0,0 +1,8 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Ehh? This could be an interesting one to implement. Could be set as the |
| 6 | + * primary data store for registered data stores in FileBackend. That would |
| 7 | + * cause it to be read first before hitting the real data store. It would also |
| 8 | + * instantly populate the cache with newly stored files |
| 9 | + */ |
\ No newline at end of file |
Property changes on: branches/FileBackend/phase3/includes/filerepo/dataStores/MemcachedDataStore.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 10 | + native |
Index: branches/FileBackend/phase3/includes/filerepo/dataStores/LocalFileSystemDataStore.php |
— | — | @@ -0,0 +1,6 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + |
| 6 | + * @todo Create a module for the FileBackend that extends AbstractFileStore to implement the logic for using the local file system as a data store |
| 7 | + */ |
\ No newline at end of file |
Property changes on: branches/FileBackend/phase3/includes/filerepo/dataStores/LocalFileSystemDataStore.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 8 | + native |
Index: branches/FileBackend/phase3/includes/filerepo/FileBackend.php |
— | — | @@ -1,123 +1,232 @@ |
2 | 2 | <?php |
3 | 3 | |
| 4 | +/** |
| 5 | + * Handles all operations on real files. The FileBacked is designed to be an |
| 6 | + * abstraction layer that allows developers to create a new class that extends |
| 7 | + * this class to use any arbitrary data store for media uploads. To manipulate |
| 8 | + * files contained within the current MediaWiki installation the dev/extension |
| 9 | + * writer need only to interact with the doOps() method in this class |
| 10 | + * |
| 11 | + * PLEASE PLEASE leave feedback on improving this file abstraction layer |
| 12 | + * |
| 13 | + * @todo Implement streamFile |
| 14 | + * @todo Implement enumFiles |
| 15 | + * @todo Design and implement smart file chunking uploads |
| 16 | + * @todo Fill in $this->validOperations via reflection into AbstractDataStore |
| 17 | + * @todo implement a method to ensure there is a primary store that registerDataStore can use |
| 18 | + * @todo Alter registerDataStore with the above to set incoming data store as primary if one does not exist |
| 19 | + * @todo Alter registerDataStore to alter the current primary to false if isPrimaryStore is set to true on incoming |
| 20 | + * @todo Register data store in global and existing in includes/filerepo/dataStores inside of constructor |
| 21 | + */ |
4 | 22 | abstract class FileBackend { |
5 | 23 | |
| 24 | + /* |
| 25 | + * This could potentially be populated via reflection. Look at the methods |
| 26 | + * available in the AbstratDataStore object |
| 27 | + */ |
| 28 | + protected $validOperations = array('store'/* add a new file to data store */, |
| 29 | + 'relocate' /* used to relocate all files in store */, |
| 30 | + 'copy', |
| 31 | + 'delete', |
| 32 | + 'move', |
| 33 | + 'concatinate', |
| 34 | + 'fileExists', |
| 35 | + 'getFileProps', |
| 36 | + 'getLocalCopy' |
| 37 | + /* 'streamFile' not yet implemented , */ |
| 38 | + /* 'enumFiles' not yet implemented*/ |
| 39 | + ); |
6 | 40 | |
| 41 | + private $registeredDataStores = array(); |
| 42 | + |
| 43 | + /** |
| 44 | + * Constructor, currently does nothing |
| 45 | + */ |
7 | 46 | public function __construct(); |
8 | 47 | |
9 | 48 | |
| 49 | + |
| 50 | + /** |
| 51 | + * This is the main entry point into the file system back end. Callers will |
| 52 | + * supply a list of operations to be performed (almost like a script) as an |
| 53 | + * array. This class will then handle handing the operations off to the |
| 54 | + * correct file store module |
| 55 | + * |
| 56 | + * For more information about a specific operation see the abstract method |
| 57 | + * definitions comment block |
| 58 | + * |
| 59 | + * Using $ops |
| 60 | + * $ops is an array of arrays. The first array holds a list of operations. |
| 61 | + * The inner array contains the parameters, E.G: |
| 62 | + * <code> |
| 63 | + * $ops = array( |
| 64 | + * array('operation' => 'store', |
| 65 | + * 'src' => '/tmp/uploads/picture.png', |
| 66 | + * 'dest' => 'zone/uploadedFilename.png' |
| 67 | + * ) |
| 68 | + * ); |
| 69 | + * </code> |
| 70 | + * @param Array $ops - Array of arrays containing N operations to execute IN ORDER |
| 71 | + * @return Status |
| 72 | + */ |
10 | 73 | public function doOps($ops) { |
11 | 74 | if(!is_array($ops)) { |
12 | 75 | throw new MWException(__METHOD__ . " not provided with an operations array"); |
13 | 76 | } |
14 | 77 | |
| 78 | + $statusObject = ''; // some sort of status object that can hold other status objects |
| 79 | + |
15 | 80 | foreach($ops AS $op) { |
16 | | - |
17 | | - switch ($op['operations']) { |
| 81 | + switch ($op['operation']) { |
18 | 82 | case 'move': |
19 | | - $this->move($params); |
| 83 | + $statusObject->append($this->commonCaller('move', $op)); |
20 | 84 | break; |
21 | 85 | case 'delete': |
22 | | - $this->delete($params); |
| 86 | + $statusObject->append($this->commonCaller('delete', $op)); |
23 | 87 | break; |
24 | 88 | case 'copy': |
25 | | - $result = $this->copy(); |
| 89 | + $statusObject->append($this->copy()); |
| 90 | + break; |
| 91 | + case 'getFileProps': |
| 92 | + $tmpFile = $this->getLocalCopy(); |
| 93 | + $statusObject->append($this->getFileProps($tmpFile)); |
26 | 94 | default: |
27 | | - throw new MWException("$op unknown in " . __METHOD__); |
| 95 | + $statusObject->append('Unknown data store operation ' . $op['operation']); |
28 | 96 | |
29 | 97 | } |
30 | 98 | } |
| 99 | + |
| 100 | + return 'STATUS OBJECT'; |
31 | 101 | } |
32 | 102 | |
33 | | - |
34 | 103 | /** |
35 | | - * Store a file to a given destination. |
36 | 104 | * |
37 | | - * @param $srcPath String: source path or virtual URL |
38 | | - * @param $dstZone String: destination zone |
39 | | - * @param $dstRel String: destination relative path |
40 | | - * @param $flags Integer: bitwise combination of the following flags: |
41 | | - * self::DELETE_SOURCE Delete the source file after upload |
42 | | - * self::OVERWRITE Overwrite an existing destination file instead of failing |
43 | | - * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the |
44 | | - * same contents as the source |
45 | | - * @return FileRepoStatus |
| 105 | + * @param <type> $dataStoreObject |
| 106 | + * @param <type> $isPrimaryStore |
46 | 107 | */ |
47 | | - abstract function store( $srcPath, $dstZone, $dstRel, $flags = 0 ); |
| 108 | + public function registerDataStoreModule($dataStoreObject, $isPrimaryStore = false) { |
| 109 | + if(is_subclassof($dataStoreObject, 'AbstractDataStore')) { |
| 110 | + $this->registeredDataStores[] = array($dataSourceObject, $isPrimaryStore); |
| 111 | + } |
| 112 | + } |
48 | 113 | |
49 | | - /** |
50 | | - * Verify that a file exists in the file store |
51 | | - * |
52 | | - * @param String $file |
53 | | - * @param Integer $flags |
54 | | - * @return Boolean |
55 | | - */ |
56 | | - abstract function fileExists( $file, $flags = 0 ); |
57 | | - |
58 | 114 | /** |
59 | | - * Move a file to the deletion archive. |
60 | | - * If no valid deletion archive exists, this may either delete the file |
61 | | - * or throw an exception, depending on the preference of the repository |
62 | | - * @param $srcRel Mixed: relative path for the file to be deleted |
63 | | - * @param $archiveRel Mixed: relative path for the archive location. |
64 | | - * Relative to a private archive directory. |
65 | | - * @return FileRepoStatus object |
66 | | - */ |
67 | | - abstract function delete( $srcRel, $archiveRel ); |
68 | | - |
69 | | - /** |
70 | | - * Moves a file from one place to another in the file store |
| 115 | + * Ensure that there are data stores registered. If not then register the |
| 116 | + * local file system as the default data store |
71 | 117 | * |
72 | | - * @param String $srcRel - Path to source file |
73 | | - * @param String $destRel - Path to new destination |
74 | | - * @return Boolean |
| 118 | + * @todo Create local data store object and set as default if no store exists |
75 | 119 | */ |
76 | | - abstract function move( $srcRel, $destRel ); |
| 120 | + private function ensureRegisteredDataStore() { |
| 121 | + if(empty($this->registeredDataStores)) { |
| 122 | + // $this->registerDataStoreModule(new LocalFileSystemDataStore()) |
| 123 | + } |
| 124 | + } |
77 | 125 | |
78 | | - abstract function copy ( $src, $dest ); |
79 | | - |
80 | | - |
81 | | - |
82 | | - |
83 | | - |
84 | | - |
85 | 126 | /** |
86 | | - * Retreive a copy of a file from the file store and place it in the local |
87 | | - * $wgTmpDirectory. A new TempLocalFile object should be created and returned |
88 | | - * that contains the local path to the file |
89 | | - * |
90 | | - * Please overload this class inside your storage module |
91 | | - * |
92 | | - * @return TempLocalFile |
| 127 | + * The commonCaller() method is used for operations that contain the same |
| 128 | + * code as many other options. It should be used as often as possible to |
| 129 | + * reduce code duplication |
| 130 | + * @param String $operation |
| 131 | + * @param Array $params |
| 132 | + * @return Status object of some sort |
93 | 133 | */ |
94 | | - abstract function getLocalCopy( $file ); |
95 | | - |
96 | | - /** |
97 | | - * Return an associative array containing the file properties |
98 | | - * |
99 | | - * @param String $file |
100 | | - * @return Array |
101 | | - */ |
102 | | - public function getFileProps( $file ) { |
103 | | - $file = $this->getLocalCopy( $file ); |
104 | | - return File::getPropsFromPath( $file->getPath() ); |
| 134 | + private function commonCaller($operation, $params) { |
| 135 | + $statusObject = ''; // new Status object of some sort |
| 136 | + foreach($this->registeredDataStores AS $store) { |
| 137 | + $statusObject->append($store->$operation($params)); |
| 138 | + } |
| 139 | + return $statusObject; |
105 | 140 | } |
106 | 141 | |
107 | | - /** |
108 | | - * Returns an associative array containing a listing of the names of the |
109 | | - * thumbnail files associated with the provided image file |
110 | | - * |
111 | | - * Please overload this class inside your storage module |
112 | | - * |
113 | | - * @param String $file - Name of file to retreive thumbnail listing for |
114 | | - * @retrun Array |
115 | | - */ |
116 | | - abstract function getThumbnailList( $file ); |
117 | 142 | |
| 143 | +// /** |
| 144 | +// * Store a file to a given destination. |
| 145 | +// * |
| 146 | +// * @param $srcPath String: source path or virtual URL |
| 147 | +// * @param $dstZone String: destination zone |
| 148 | +// * @param $dstRel String: destination relative path |
| 149 | +// * @param $flags Integer: bitwise combination of the following flags: |
| 150 | +// * self::DELETE_SOURCE Delete the source file after upload |
| 151 | +// * self::OVERWRITE Overwrite an existing destination file instead of failing |
| 152 | +// * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the |
| 153 | +// * same contents as the source |
| 154 | +// * @return FileRepoStatus |
| 155 | +// */ |
| 156 | +// abstract function store( $srcPath, $dstZone, $dstRel, $flags = 0 ); |
| 157 | +// |
| 158 | +// /** |
| 159 | +// * Verify that a file exists in the file store |
| 160 | +// * |
| 161 | +// * @param String $file |
| 162 | +// * @param Integer $flags |
| 163 | +// * @return Boolean |
| 164 | +// */ |
| 165 | +// abstract function fileExists( $file, $flags = 0 ); |
| 166 | +// |
| 167 | +// /** |
| 168 | +// * Move a file to the deletion archive. |
| 169 | +// * If no valid deletion archive exists, this may either delete the file |
| 170 | +// * or throw an exception, depending on the preference of the repository |
| 171 | +// * @param $srcRel Mixed: relative path for the file to be deleted |
| 172 | +// * @param $archiveRel Mixed: relative path for the archive location. |
| 173 | +// * Relative to a private archive directory. |
| 174 | +// * @return FileRepoStatus object |
| 175 | +// */ |
| 176 | +// abstract function delete( $srcRel, $archiveRel ); |
| 177 | +// |
| 178 | +// /** |
| 179 | +// * Moves a file from one place to another in the file store |
| 180 | +// * |
| 181 | +// * @param String $srcRel - Path to source file |
| 182 | +// * @param String $destRel - Path to new destination |
| 183 | +// * @return Boolean |
| 184 | +// */ |
| 185 | +// abstract function move( $srcRel, $destRel ); |
| 186 | +// |
| 187 | +// abstract function copy ( $src, $dest ); |
| 188 | +// |
| 189 | +// |
| 190 | +// |
| 191 | +// |
| 192 | +// |
| 193 | +// |
| 194 | +// /** |
| 195 | +// * Retreive a copy of a file from the file store and place it in the local |
| 196 | +// * $wgTmpDirectory. A new TempLocalFile object should be created and returned |
| 197 | +// * that contains the local path to the file |
| 198 | +// * |
| 199 | +// * Please overload this class inside your storage module |
| 200 | +// * |
| 201 | +// * @return TempLocalFile |
| 202 | +// */ |
| 203 | +// abstract function getLocalCopy( $file ); |
| 204 | +// |
| 205 | +// /** |
| 206 | +// * Return an associative array containing the file properties |
| 207 | +// * |
| 208 | +// * @param String $file |
| 209 | +// * @return Array |
| 210 | +// */ |
| 211 | +// public function getFileProps( $file ) { |
| 212 | +// $file = $this->getLocalCopy( $file ); |
| 213 | +// return File::getPropsFromPath( $file->getPath() ); |
| 214 | +// } |
| 215 | +// |
| 216 | +// /** |
| 217 | +// * Returns an associative array containing a listing of the names of the |
| 218 | +// * thumbnail files associated with the provided image file |
| 219 | +// * |
| 220 | +// * Please overload this class inside your storage module |
| 221 | +// * |
| 222 | +// * @param String $file - Name of file to retreive thumbnail listing for |
| 223 | +// * @retrun Array |
| 224 | +// */ |
| 225 | +// abstract function getThumbnailList( $file ); |
| 226 | +// |
| 227 | +// |
| 228 | +// |
| 229 | +// public function addChunk() { throw new MWException( __METHOD__ . ' not yet implemented.' ); } |
| 230 | +// public function concatenateChunks() { throw new MWException( __METHOD__ . ' not yet implemented.' ); } |
118 | 231 | |
119 | | - |
120 | | - public function addChunk() { throw new MWException( __METHOD__ . ' not yet implemented.' ); } |
121 | | - public function concatenateChunks() { throw new MWException( __METHOD__ . ' not yet implemented.' ); } |
122 | | - |
123 | 232 | |
124 | 233 | } // end class |
\ No newline at end of file |