1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
|
<?php
/* vim:set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab: */
/**
* Sort Files
*
*
* LICENSE: GNU General Public License, version 2 (GPLv2)
* Copyright (c) 2001 - 2011 Ampache.org All Rights Reserved
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License v2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* @package Ampache
* @copyright 2001 - 2011 Ampache.org
* @license http://opensource.org/licenses/gpl-2.0 GPLv2
* @link http://www.ampache.org/
*/
/**
* Still not fully tested but "Appears to work" use at your own risk
* sort_files
* This script has a lot of stuff to worry about. It's primary duty is to re-organize
* your files based on some sane, and predefined (in the interface) order using the
* tag information gathered and updated in ampache. Sort_Pattern defines the directory
* structure and rename_pattern defines the file pattern. This script should allow you
* to do both or neither. Oooh and allow you to sort with A,B,C,D prefix
*
* Attempt 1 - Do each file one by one and satisfy the needs of each file by its self (this is going to be slow)
* Cache information so we don't have to check for every file!
*/
/* Don't do anything just tell me what you would do */
//$test_mode = true;
/* m(__)m */
$alphabet_prefix = true;
define('NO_SESSION','1');
$path = dirname(__FILE__);
$prefix = realpath($path . '/../');
require_once $prefix . '/lib/init.php';
ob_end_clean();
/* First Clean the catalog to we don't try to write anything we shouldn't */
$sql = "SELECT `id` FROM `catalog` WHERE `catalog_type`='local'";
$db_results = Dba::read($sql);
$catalogs = array();
while ($r = Dba::fetch_row($db_results)) {
$catalog = new Catalog($r['0']);
$songs = $catalog->get_catalog_files();
printf (_('Starting Catalog: %s'), stripslashes($catalog->name));
echo "\n";
/* Foreach through each file and find it a home! */
foreach ($songs as $song) {
/* Find this poor song a home */
$song->format();
$song->format_pattern();
$directory = sort_find_home($song,$catalog->sort_pattern,$catalog->path);
$filename = $song->f_file;
$fullpath = $directory . "/" . $filename;
/* Check for Demo Mode */
if ($test_mode) {
/* We're just talking here... no work */
echo _("Moving File...");
echo "\n\t";
printf (_('Source: %s'), $song->file);
echo "\n\t";
printf (_('Dest: %s'), $fullpath);
echo "\n";
flush();
}
/* We need to actually do the moving (fake it if we are testing)
* Don't try to move it, if it's already the same friggin thing!
*/
if ($song->file != $fullpath && strlen($fullpath)) {
sort_move_file($song,$fullpath);
}
} // end foreach song
} // end foreach catalogs
/************** FUNCTIONS *****************/
/**
* sort_find_home
* Get the directory for this file from the catalog and the song info using the sort_pattern
* takes into account various artists and the alphabet_prefix
*/
function sort_find_home($song,$sort_pattern,$base) {
$home = rtrim($base,"\/");
$home = rtrim($home,"\\");
/* Create the filename that this file should have */
$album = sort_clean_name($song->f_album_full);
$artist = sort_clean_name($song->f_artist_full);
$track = sort_clean_name($song->track);
$title = sort_clean_name($song->title);
$year = sort_clean_name($song->year);
$comment = sort_clean_name($song->comment);
/* Do the various check */
$album_object = new Album($song->album);
$album_object->format();
if ($album_object->artist_count != '1') {
$artist = "Various";
}
/* IF we want a,b,c,d we need to know the first element */
if ($GLOBALS['alphabet_prefix']) {
$sort_pattern = preg_replace("/\/?%o\//","",$sort_pattern);
$first_element = substr($sort_pattern,0,2);
$element = sort_element_name($first_element);
if (!$element) { $alphabet = 'ZZ'; }
else { $alphabet = strtoupper(substr(${$element},0,1)); }
$alphabet = preg_replace("/[^A-Za-z0-9]/","ZZ",$alphabet);
$home .= "/$alphabet";
}
/* Replace everything we can find */
$replace_array = array('%a','%A','%t','%T','%y','%c');
$content_array = array($artist,$album,$title,$track,$year,$comment);
$sort_pattern = str_replace($replace_array,$content_array,$sort_pattern);
/* Remove non A-Z0-9 chars */
$sort_pattern = preg_replace("[^\\\/A-Za-z0-9\-\_\ \'\,\(\)]","_",$sort_pattern);
$home .= "/$sort_pattern";
return $home;
} // sort_find_home
/**
* sort_element_name
* gets the name of the %? in a yea.. too much beer
*/
function sort_element_name($key) {
switch ($key) {
case '%t':
return 'title';
break;
case '%T':
return 'track';
break;
case '%a':
return 'artist';
break;
case '%A':
return 'album';
break;
case '%y':
return 'year';
break;
default:
break;
} // switch on key
return false;
} // sort_element_name
/**
* sort_clean_name
* We have to have some special rules here
* This is run on every individual element of the search
* Before it is put togeather, this removes / and \ and also
* once I figure it out, it'll clean other stuff
*/
function sort_clean_name($string) {
/* First remove any / or \ chars */
$string = preg_replace('/[\/\\\]/','-',$string);
$string = str_replace(':',' ',$string);
$string = preg_replace('/[\!\:\*]/','_',$string);
return $string;
} // sort_clean_name
/**
* sort_move_file
* All this function does is, move the friggin file and then update the database
* We can't use the rename() function of PHP because it's functionality depends on the
* current phase of the moon, the alignment of the planets and my current BAL
* Instead we cheeseball it and walk through the new dir structure and make
* sure that the directories exist, once the dirs exist then we do a copy
* and unlink.. This is a little unsafe, and as such it verifys the copy
* worked by doing a filesize() before unlinking.
*/
function sort_move_file($song,$fullname) {
$old_dir = dirname($song->file);
$info = pathinfo($fullname);
$directory = $info['dirname'];
$file = $info['basename'];
$data = preg_split("/[\/\\\]/",$directory);
$path = '';
/* We not need the leading / */
unset($data[0]);
foreach ($data as $dir) {
$dir = sort_clean_name($dir);
$path .= "/" . $dir;
/* We need to check for the existance of this directory */
if (!is_dir($path)) {
if ($GLOBALS['test_mode']) {
echo "\t";
printf (_('Making %s Directory'), $path);
echo "\n";
}
else {
debug_event('mkdir',"Creating $path directory",'5');
$results = mkdir($path);
if (!$results) {
printf (_('Error: Unable to create %s move failed'), $path);
echo "\n";
return false;
}
} // else we aren't in test mode
} // if it's not a dir
} // foreach dir
/* Now that we've got the correct directory structure let's try to copy it */
if ($GLOBALS['test_mode']) {
echo "\t";
// HINT: %1$s: file, %2$s: directory
printf (_('Copying %1$s to %2$s'), $file, $directory);
echo "\n";
$sql = "UPDATE song SET file='" . Dba::escape($fullname) . "' WHERE id='" . Dba::escape($song->id) . "'";
echo "\tSQL: $sql\n";
flush();
}
else {
/* Check for file existance */
if (file_exists($fullname)) {
debug_event('file exists','Error: $fullname already exists','1');
printf (_('Error: %s already exists'), $filename);
echo "\n";
return false;
}
$results = copy($song->file,$fullname);
debug_event('copy','Copied ' . $song->file . ' to ' . $fullname,'5');
/* Look for the folder art and copy that as well */
if (!Config::get('album_art_preferred_filename') OR strstr(Config::get('album_art_preferred_filename'),"%")) {
$folder_art = $directory . '/folder.jpg';
$old_art = $old_dir . '/folder.jpg';
}
else {
$folder_art = $directory . "/" . sort_clean_name(Config::get('album_art_preferred_filename'));
$old_art = $old_dir . "/" . sort_clean_name(Config::get('album_art_preferred_filename'));
}
debug_event('copy_art','Copied ' . $old_art . ' to ' . $folder_art,'5');
@copy($old_art,$folder_art);
if (!$results) { printf (_('Error: Unable to copy file to %s'), $fullname); echo "\n"; return false; }
/* Check the filesize */
$new_sum = filesize($fullname);
$old_sum = filesize($song->file);
if ($new_sum != $old_sum OR !$new_sum) {
printf (_('Error: Size Inconsistency, not deleting %s'), $song->file);
echo "\n";
return false;
} // end if sum's don't match
/* If we've made it this far it should be safe */
$results = unlink($song->file);
if (!$results) { printf (_('Error: Unable to delete %s'), $song->file); echo "\n"; }
/* Update the catalog */
$sql = "UPDATE song SET file='" . Dba::escape($fullname) . "' WHERE id='" . Dba::escape($song->id) . "'";
$db_results = Dba::write($sql);
} // end else
return true;
} // sort_move_file
?>
|