OSDN Git Service

MERGE: リビジョン1864。Mediaクラス、MediaObjectクラスのコード整理。
[nucleus-jp/nucleus-next.git] / nucleus / libs / MEDIA.php
1 <?php\r
2 /*\r
3  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
4  * Copyright (C) 2002-2012 The Nucleus Group\r
5  *\r
6  * This program is free software; you can redistribute it and/or\r
7  * modify it under the terms of the GNU General Public License\r
8  * as published by the Free Software Foundation; either version 2\r
9  * of the License, or (at your option) any later version.\r
10  * (see nucleus/documentation/index.html#license for more info)\r
11  */\r
12 /**\r
13  * Media classes for nucleus\r
14  *\r
15  * @license http://nucleuscms.org/license.txt GNU General Public License\r
16  * @copyright Copyright (C) 2002-2012 The Nucleus Group\r
17  * @version $Id: MEDIA.php 1864 2012-05-19 11:39:44Z sakamocchi $
18  */\r
19 \r
20 define('PRIVATE_COLLECTION',            'Private Collection');\r
21 define('READ_ONLY_MEDIA_FOLDER',        '(Read Only)');\r
22 \r
23 class Media\r
24 {\r
25         /**\r
26          * Media::getCollectionList()\r
27          * Gets the list of collections available to the currently logged\r
28          * in member\r
29          *\r
30          * @returns array of dirname => display name\r
31          */\r
32         static public function getCollectionList($exceptReadOnly = FALSE)\r
33         {\r
34                 global $member, $DIR_MEDIA;\r
35                 \r
36                 $collections = array();\r
37                 \r
38                 // add private directory for member\r
39                 $collections[$member->getID()] = PRIVATE_COLLECTION;\r
40                 \r
41                 // add global collections\r
42                 if ( !is_dir($DIR_MEDIA) )\r
43                 {\r
44                         return $collections;\r
45                 }\r
46                 \r
47                 $dirhandle = opendir($DIR_MEDIA);\r
48                 while ( $dirname = readdir($dirhandle) )\r
49                 {\r
50                         // only add non-numeric (numeric=private) dirs\r
51                         if ( @is_dir($DIR_MEDIA . $dirname) &&\r
52                                 ($dirname != '.') &&\r
53                                 ($dirname != '..') &&\r
54                                 ($dirname != 'CVS') &&\r
55                                 (!is_numeric($dirname)) )\r
56                                 {\r
57                                 if ( @is_writable($DIR_MEDIA . $dirname) )\r
58                                 {\r
59                                         $collections[$dirname] = $dirname;\r
60                                 }\r
61                                 else if ( $exceptReadOnly == FALSE )\r
62                                 {\r
63                                         $collections[$dirname] = $dirname . ' ' . READ_ONLY_MEDIA_FOLDER;\r
64                                 }\r
65                         }\r
66                 }\r
67                 closedir($dirhandle);\r
68                 \r
69                 return $collections;\r
70         }\r
71         \r
72         /**\r
73          * Media::getMediaListByCollection()\r
74          * Returns an array of MediaObject objects for a certain collection\r
75          *\r
76          * @param       string  $collection     name of the collection\r
77          * @param       string  $filter         filter on filename (defaults to none)\r
78          * @return      void\r
79          */\r
80         static public function getMediaListByCollection($collection, $filter = '')\r
81         {\r
82                 global $CONF, $DIR_MEDIA;\r
83                 \r
84                 $filelist = array();\r
85                 \r
86                 // 1. go through all objects and add them to the filelist\r
87                 $mediadir = $DIR_MEDIA . $collection . '/';\r
88                 \r
89                 // return if dir does not exist\r
90                 if ( !is_dir($mediadir) )\r
91                 {\r
92                         return $filelist;\r
93                 }\r
94                 \r
95                 $dirhandle = opendir($mediadir);\r
96                 while ( $filename = readdir($dirhandle) )\r
97                 {\r
98                         // only add files that match the filter\r
99                         if ( !@is_dir($filename) && self::checkFilter($filename, $filter) )\r
100                         {\r
101                                 array_push($filelist, new MediaObject($collection, $filename, filemtime($mediadir . $filename)));\r
102                         }\r
103                 }\r
104                 closedir($dirhandle);\r
105                 \r
106                 // sort array so newer files are shown first\r
107                 usort($filelist,  array(__CLASS__, 'sort_media'));\r
108                 \r
109                 return $filelist;\r
110         }\r
111         \r
112         /**\r
113          * Media::checkFilter()\r
114          * \r
115          * @param       string  $strText\r
116          * @param       string  $strFilter\r
117          * @return      boolean\r
118          */\r
119         static public function checkFilter($strText, $strFilter)\r
120         {\r
121                 if ( $strFilter == '' )\r
122                 {\r
123                         return 1;\r
124                 }\r
125                 else\r
126                 {\r
127                         return is_integer(i18n::strpos(strtolower($strText), strtolower($strFilter)));\r
128                 }\r
129         }\r
130         \r
131         /**\r
132          * Media::isValidCollection()\r
133          * checks if a collection exists with the given name, and if it's\r
134          * allowed for the currently logged in member to upload files to it\r
135          * \r
136          * @param       string  $collectionName\r
137          * @param       string  $exceptReadOnly\r
138          * @return      boolean\r
139          */\r
140         static public function isValidCollection($collectionName, $exceptReadOnly = FALSE)\r
141         {\r
142                 global $member, $DIR_MEDIA;\r
143                 \r
144                 // allow creating new private directory\r
145                 if ( $collectionName === (string)$member->getID() )\r
146                 {\r
147                         return TRUE;\r
148                 }\r
149                 \r
150                 $collections = self::getCollectionList($exceptReadOnly);\r
151                 $dirname = $collections[$collectionName];\r
152                 \r
153                 if ( $dirname == NULL || $dirname === PRIVATE_COLLECTION )\r
154                 {\r
155                         return FALSE;\r
156                 }\r
157                 \r
158                 // other collections should exist and be writable\r
159                 $collectionDir = $DIR_MEDIA . $collectionName;\r
160                 if ( $exceptReadOnly )\r
161                 {\r
162                         return ( @is_dir($collectionDir) && @is_writable($collectionDir) );\r
163                 }\r
164                 \r
165                 // other collections should exist\r
166                 return @is_dir($collectionDir);\r
167         }\r
168         \r
169         /**\r
170          * Media::addMediaObject()\r
171          * Adds an uploaded file to the media archive\r
172          *\r
173          * @param       string  $collection     collection\r
174          * @param       array   $uploadfile     the postFileInfo(..) array\r
175          * @param       string  $filename       the filename that should be used to save the file as\r
176          *                                                              (date prefix should be already added here)\r
177          * @return      string  blank if success, message if failed\r
178          */\r
179         static public function addMediaObject($collection, $uploadfile, $filename)\r
180         {\r
181                 global $DIR_MEDIA, $manager;\r
182                 \r
183                 // clean filename of characters that may cause trouble in a filename using cleanFileName() function from globalfunctions.php\r
184                 $filename = cleanFileName($filename);\r
185                 \r
186                 // should already have tested for allowable types before calling this method. This will only catch files with no extension at all\r
187                 if ( $filename === FALSE )\r
188                 {\r
189                         return _ERROR_BADFILETYPE;\r
190                 }\r
191                 \r
192                 // trigger PreMediaUpload event\r
193                 $manager->notify('PreMediaUpload',array('collection' => &$collection, 'uploadfile' => $uploadfile, 'filename' => &$filename));\r
194                 \r
195                 // don't allow uploads to unknown or forbidden collections\r
196                 $exceptReadOnly = TRUE;\r
197                 if ( !self::isValidCollection($collection,$exceptReadOnly) )\r
198                 {\r
199                         return _ERROR_DISALLOWED;\r
200                 }\r
201                 \r
202                 // check dir permissions (try to create dir if it does not exist)\r
203                 $mediadir = $DIR_MEDIA . $collection;\r
204                 \r
205                 // try to create new private media directories if needed\r
206                 if ( !@is_dir($mediadir) && is_numeric($collection) )\r
207                 {\r
208                         $oldumask = umask(0000);\r
209                         if ( !@mkdir($mediadir, 0777) )\r
210                         {\r
211                                 return _ERROR_BADPERMISSIONS;\r
212                         }\r
213                         umask($oldumask);\r
214                 }\r
215                 \r
216                 // if dir still not exists, the action is disallowed\r
217                 if ( !@is_dir($mediadir) )\r
218                 {\r
219                         return _ERROR_DISALLOWED;\r
220                 }\r
221                 \r
222                 if ( !is_writeable($mediadir) )\r
223                 {\r
224                         return _ERROR_BADPERMISSIONS;\r
225                 }\r
226                 \r
227                 // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems)\r
228                 $mediadir .= '/';\r
229                 \r
230                 if ( file_exists($mediadir . $filename) )\r
231                 {\r
232                         return _ERROR_UPLOADDUPLICATE;\r
233                 }\r
234                 \r
235                 // move file to directory\r
236                 if ( is_uploaded_file($uploadfile) )\r
237                 {\r
238                         if ( !@move_uploaded_file($uploadfile, $mediadir . $filename) )\r
239                         {\r
240                                 return _ERROR_UPLOADMOVEP;\r
241                         }\r
242                 }\r
243                 else\r
244                 {\r
245                         if ( !copy($uploadfile, $mediadir . $filename) )\r
246                         {\r
247                                 return _ERROR_UPLOADCOPY ;\r
248                         }\r
249                 }\r
250                 \r
251                 // chmod uploaded file\r
252                 $oldumask = umask(0000);\r
253                 @chmod($mediadir . $filename, 0644);\r
254                 umask($oldumask);\r
255                 \r
256                 $manager->notify('PostMediaUpload',array('collection' => $collection, 'mediadir' => $mediadir, 'filename' => $filename));\r
257                 \r
258                 return '';\r
259         }\r
260         \r
261         /**\r
262          * Media::addMediaObjectRaw()\r
263          * Adds an uploaded file to the media dir.\r
264          * \r
265          * NOTE: does not check if $collection is valid.\r
266          * \r
267          * @param       string  $collection     collection to use\r
268          * @param       string  $filename       the filename that should be used to save the file\r
269          *                                                              as (date prefix should be already added here)\r
270          * @param       &$data  File data (binary)\r
271          * @return      string  blank if success, message if failed\r
272          */\r
273         static public function addMediaObjectRaw($collection, $filename, &$data)\r
274         {\r
275                 global $DIR_MEDIA;\r
276                 \r
277                 // check dir permissions (try to create dir if it does not exist)\r
278                 $mediadir = $DIR_MEDIA . $collection;\r
279                 \r
280                 // try to create new private media directories if needed\r
281                 if ( !@is_dir($mediadir) && is_numeric($collection) )\r
282                 {\r
283                         $oldumask = umask(0000);\r
284                         if ( !@mkdir($mediadir, 0777) )\r
285                         {\r
286                                 return _ERROR_BADPERMISSIONS;\r
287                         }\r
288                         umask($oldumask);\r
289                 }\r
290                 \r
291                 // if dir still not exists, the action is disallowed\r
292                 if ( !@is_dir($mediadir) )\r
293                 {\r
294                         return _ERROR_DISALLOWED;\r
295                 }\r
296                 \r
297                 if ( !is_writeable($mediadir) )\r
298                 {\r
299                         return _ERROR_BADPERMISSIONS;\r
300                 }\r
301                 \r
302                 // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems)\r
303                 $mediadir .= '/';\r
304                 \r
305                 if ( file_exists($mediadir . $filename) )\r
306                 {\r
307                         return _ERROR_UPLOADDUPLICATE;\r
308                 }\r
309                 \r
310                 // create file\r
311                 $fh = @fopen($mediadir . $filename, 'wb');\r
312                 if ( !$fh )\r
313                 {\r
314                         return _ERROR_UPLOADFAILED;\r
315                 }\r
316                 $ok = @fwrite($fh, $data);\r
317                 @fclose($fh);\r
318                 if ( !$ok )\r
319                 {\r
320                         return _ERROR_UPLOADFAILED;\r
321                 }\r
322                 \r
323                 // chmod uploaded file\r
324                 $oldumask = umask(0000);\r
325                 @chmod($mediadir . $filename, 0644);\r
326                 umask($oldumask);\r
327                 \r
328                 return '';\r
329         }\r
330         \r
331         /**\r
332          * Media::sort_media()\r
333          * User-defined sort method to sort an array of MediaObjects\r
334          * \r
335          * @param       object  $a\r
336          * @param       object  $b\r
337          * @return      boolean\r
338          */\r
339         static private function sort_media($a, $b)\r
340         {\r
341                 if ($a->timestamp == $b->timestamp) return 0;\r
342                 return ($a->timestamp > $b->timestamp) ? -1 : 1;\r
343         }\r
344 }\r
345 \r
346 /**\r
347  * Represents the characteristics of one single media-object\r
348  *\r
349  * Description of properties:\r
350  *  - filename: filename, without paths\r
351  *  - timestamp: last modification (unix timestamp)\r
352  *  - collection: collection to which the file belongs (can also be a owner ID, for private collections)\r
353  *  - private: true if the media belongs to a private member collection\r
354  */\r
355 class MediaObject\r
356 {\r
357         public $private;\r
358         public $collection;\r
359         public $filename;\r
360         public $timestamp;\r
361         \r
362         public function __construct($collection, $filename, $timestamp)\r
363         {\r
364                 $this->private = is_numeric($collection);\r
365                 $this->collection = $collection;\r
366                 $this->filename = $filename;\r
367                 $this->timestamp = $timestamp;\r
368                 return;\r
369         }\r
370 }\r