-
Notifications
You must be signed in to change notification settings - Fork 0
/
class-orphaned-list-table.php
253 lines (205 loc) · 7.45 KB
/
class-orphaned-list-table.php
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
<?php
if ( ! class_exists ( 'WP_List_Table' ) ) {
require_once ( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class OrphanedListTable extends WP_List_Table {
function __construct( $args = array() ) {
parent::__construct( array(
'singular' => 'file',
'plural' => 'files',
'ajax' => false
) );
}
function column_default( $item, $column_name ) {
return $item[$column_name];
}
function column_preview( $item ) {
$wp_upload_dir = wp_upload_dir ();
$upload_folder = $wp_upload_dir['baseurl'];
return '<img style="max-height: 60px;max-width: 80px;" src="'.$upload_folder.$item['file'].'" />';
}
function column_date( $item ) {
if ( ( abs( time() - $item['date'] ) ) < 86400 ) {
$time = human_time_diff( $item['date'] )." ago";
} else {
$time = date( 'Y/m/d', $item['date'] );
}
return $time;
}
function column_file( $item ) {
$actions = array( 'add' => '<a href="?page=orphaned&add=true&file='.urlencode( $item['file'] ).'">Add to Media Library</a>' );
return $item['file'].$this->row_actions($actions);
}
function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
/*$1%s*/ 'add_to_media',
/*$2%s*/ $item['file']
);
}
function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
'preview' => '',
'file' => 'File',
'date' => 'Date'
);
return $columns;
}
function get_bulk_actions() {
$actions = array(
'mass-add' => 'Add to library'
);
return $actions;
}
/**
* Watches for requests to do something with the files, and then does it.
*/
function handle_actions () {
// There's no "add this file to library" function that doesn't also try to upload it, so we'll have to take
// parts of the code out ourselves to use here.
// This is a bastardised version of media_handle_sideload(), from wp-admin/includes/media.php
function add_to_media($file) {
$url = $file['url'];
$type = $file['type'];
$file = $file['file'];
$title = preg_replace( '/\.[^.]+$/', '', basename( $file ) );
$content = '';
// use image exif/iptc data for title and caption defaults if possible
if ( $image_meta = @wp_read_image_metadata($file) ) {
if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) )
$title = $image_meta['title'];
if ( trim( $image_meta['caption'] ) )
$content = $image_meta['caption'];
}
// Construct the attachment array
$wp_filetype = wp_check_filetype( basename( $file ), null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'guid' => $url,
'post_parent' => 0,
'post_title' => $title,
'post_content' => $content,
'post_status' => 'inherit'
);
// Save the attachment metadata
$id = wp_insert_attachment( $attachment, $file );
if ( !is_wp_error($id) )
wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) );
return $id;
}
if ($_GET['add'] == true && isset( $_GET['file'] )) {
$path_parts = pathinfo( $_GET['file'] );
$wp_upload_dir = wp_upload_dir ();
$upload_folder = $wp_upload_dir['basedir'];
$file_array = array (
'file' => $upload_folder.$_GET['file'],
'url' => $wp_upload_dir['url']."/".$_GET['file'],
'type' => ''
);
add_to_media( $file_array );
} elseif( $_GET['action'] == "mass-add") {
if (count ($_GET['add_to_media'])) {
foreach ($_GET['add_to_media'] as $file) {
$path_parts = pathinfo( $file );
$wp_upload_dir = wp_upload_dir ();
$upload_folder = $wp_upload_dir['basedir'];
$file_array = array (
'file' => $upload_folder.$file,
'url' => $wp_upload_dir['url']."/".$file,
'type' => ''
);
add_to_media( $file_array );
}
}
}
}
function prepare_items() {
$this->handle_actions ();
$per_page = 10;
$columns = $this->get_columns();
$hidden = array();
$sortable = array();
$this->_column_headers = array($columns, $hidden, $sortable);
$data = $this->getData ();
$current_page = $this->get_pagenum();
$total_items = count($data);
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
$this->items = $data;
$this->set_pagination_args ( array(
'total_items' => $total_items,
'per_page' => $per_page,
'total_pages' => ceil($total_items/$per_page)
) );
}
/**
* Compares what files are in the upload directory, and finds any that aren't in the Media Library, and
* returns them.
*
* @return array
*/
function getData () {
global $wpdb;
$orphaned_files = array();
// where's the upload folder?
$wp_upload_dir = wp_upload_dir ();
$upload_folder = $wp_upload_dir['basedir'];
// in a bit, we'll be checking to see if the file we're looking at is in the wp_postmeta table as '_wp_attached_file',
// however that will only tell us about original images. resized images are stored in wp_postmeta as '_wp_attachment_backup_sizes',
// and '_wp_attachment_metadata'. The issue there is that they're inside serialised arrays! We should unserialise all those
// values and keep an array of every mentioned file.
$arr_metadata = $wpdb->get_results( 'SELECT * FROM '.$wpdb->postmeta.' WHERE meta_key = "_wp_attachment_metadata"', ARRAY_A );
foreach( (array)$arr_metadata as $metadata ) {
$clean_meta = unserialize( $metadata['meta_value'] );
$filename = pathinfo ($clean_meta['file']);
$ignore_file[] = $filename['basename'];
foreach ( (array)$clean_meta['sizes'] as $size ) {
if ( !empty( $size['file'] ) ) $ignore_file[] = $size['file'];
}
}
$arr_metadata = $wpdb->get_results( 'SELECT * FROM '.$wpdb->postmeta.' WHERE meta_key = "_wp_attachment_backup_sizes"', ARRAY_A );
foreach( (array)$arr_metadata as $metadata ) {
$clean_meta = unserialize( $metadata['meta_value'] );
foreach ( (array)$clean_meta as $size ) {
if ( !empty( $size['file'] ) ) $ignore_file[] = $size['file'];
}
}
// we'll start checking from the upload folder.
// this variable will contain an array of the folders we need to look into.
$to_check = array(NULL);
// Whilst there's an element in $to_check, we'll keep checking it.
while ( count ( $to_check ) ) {
$to_check[0] .= "/";
$full_path = $upload_folder.$to_check[0];
$scanned_dir = scandir ( $full_path );
foreach ( $scanned_dir as $path ) {
if ( $path == '.' || $path == '..' ) continue;
if ( is_dir ( $full_path.$path ) ) {
// since it's a directory, we need to look through that too.
$to_check[] = $to_check[0].$path;
} else {
$post_id = $wpdb->get_var ( 'SELECT post_id FROM '.$wpdb->postmeta.' WHERE meta_key = "_wp_attached_file" AND meta_value = "'.trim ($to_check[0].$path, '/').'"' );
if ( ! (bool) $post_id ) {
// make sure this filename isn't in the one's we're ignoring
$filename = pathinfo ($path);
$filename = $filename['basename'];
if ( !in_array( $filename, (array)$ignore_file ))
$orphaned_files[] = $to_check[0].$path;
}
}
}
// remove [0]...
array_shift ( $to_check );
}
// now we can format these files in a way that the list table object needs them
$data = array();
foreach ( $orphaned_files as $file_path ) {
$data[] = array (
'file' => $file_path,
'date' => filemtime ( $upload_folder.$file_path )
);
}
return $data;
}
}
?>