| Conditions | 28 |
| Paths | 116 |
| Total Lines | 268 |
| Code Lines | 186 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 114 | public function data(Request $request): JsonResponse { |
||
| 115 | $files = $request->get('files'); // local|external|unused |
||
| 116 | $search = $request->get('search'); |
||
| 117 | $search = $search['value']; |
||
| 118 | $start = (int) $request->get('start'); |
||
| 119 | $length = (int) $request->get('length'); |
||
| 120 | |||
| 121 | // family tree setting MEDIA_DIRECTORY |
||
| 122 | $media_folders = $this->allMediaFolders(); |
||
| 123 | $media_folder = $request->get('media_folder', ''); |
||
| 124 | // User folders may contain special characters. Restrict to actual folders. |
||
| 125 | if (!array_key_exists($media_folder, $media_folders)) { |
||
| 126 | $media_folder = reset($media_folders); |
||
| 127 | } |
||
| 128 | |||
| 129 | // prefix to filename |
||
| 130 | $media_paths = $this->mediaPaths($media_folder); |
||
| 131 | $media_path = $request->get('media_path', ''); |
||
| 132 | // User paths may contain special characters. Restrict to actual paths. |
||
| 133 | if (!array_key_exists($media_path, $media_paths)) { |
||
| 134 | $media_path = reset($media_paths); |
||
| 135 | } |
||
| 136 | |||
| 137 | // subfolders within $media_path |
||
| 138 | $subfolders = $request->get('subfolders'); // include|exclude |
||
| 139 | |||
| 140 | switch ($files) { |
||
| 141 | case 'local': |
||
| 142 | // Filtered rows |
||
| 143 | $SELECT1 = |
||
| 144 | "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS TRIM(LEADING :media_path_1 FROM multimedia_file_refn) AS media_path, m_id AS xref, descriptive_title, m_file AS gedcom_id, m_gedcom AS gedcom" . |
||
| 145 | " FROM `##media`" . |
||
| 146 | " JOIN `##media_file` USING (m_file, m_id)" . |
||
| 147 | " JOIN `##gedcom_setting` ON (m_file = gedcom_id AND setting_name = 'MEDIA_DIRECTORY')" . |
||
| 148 | " JOIN `##gedcom` USING (gedcom_id)" . |
||
| 149 | " WHERE setting_value = :media_folder" . |
||
| 150 | " AND multimedia_file_refn LIKE CONCAT(:media_path_2, '%')" . |
||
| 151 | " AND (SUBSTRING_INDEX(multimedia_file_refn, '/', -1) LIKE CONCAT('%', :search_1, '%')" . |
||
| 152 | " OR descriptive_title LIKE CONCAT('%', :search_2, '%'))" . |
||
| 153 | " AND multimedia_file_refn NOT LIKE 'http://%'" . |
||
| 154 | " AND multimedia_file_refn NOT LIKE 'https://%'"; |
||
| 155 | $ARGS1 = [ |
||
| 156 | 'media_path_1' => $media_path, |
||
| 157 | 'media_folder' => $media_folder, |
||
| 158 | 'media_path_2' => Database::escapeLike($media_path), |
||
| 159 | 'search_1' => Database::escapeLike($search), |
||
| 160 | 'search_2' => Database::escapeLike($search), |
||
| 161 | ]; |
||
| 162 | // Unfiltered rows |
||
| 163 | $SELECT2 = |
||
| 164 | "SELECT SQL_CACHE COUNT(*)" . |
||
| 165 | " FROM `##media`" . |
||
| 166 | " JOIN `##media_file` USING (m_file, m_id)" . |
||
| 167 | " JOIN `##gedcom_setting` ON (m_file = gedcom_id AND setting_name = 'MEDIA_DIRECTORY')" . |
||
| 168 | " WHERE setting_value = :media_folder" . |
||
| 169 | " AND multimedia_file_refn LIKE CONCAT(:media_path_3, '%')" . |
||
| 170 | " AND multimedia_file_refn NOT LIKE 'http://%'" . |
||
| 171 | " AND multimedia_file_refn NOT LIKE 'https://%'"; |
||
| 172 | $ARGS2 = [ |
||
| 173 | 'media_folder' => $media_folder, |
||
| 174 | 'media_path_3' => $media_path, |
||
| 175 | ]; |
||
| 176 | |||
| 177 | if ($subfolders == 'exclude') { |
||
| 178 | $SELECT1 .= " AND multimedia_file_refn NOT LIKE CONCAT(:media_path_4, '%/%')"; |
||
| 179 | $ARGS1['media_path_4'] = Database::escapeLike($media_path); |
||
| 180 | $SELECT2 .= " AND multimedia_file_refn NOT LIKE CONCAT(:media_path_4, '%/%')"; |
||
| 181 | $ARGS2['media_path_4'] = Database::escapeLike($media_path); |
||
| 182 | } |
||
| 183 | |||
| 184 | $order = $request->get('order', []); |
||
| 185 | $SELECT1 .= " ORDER BY "; |
||
| 186 | if ($order) { |
||
| 187 | foreach ($order as $key => $value) { |
||
| 188 | if ($key > 0) { |
||
| 189 | $SELECT1 .= ','; |
||
| 190 | } |
||
| 191 | // Columns in datatables are numbered from zero. |
||
| 192 | // Columns in MySQL are numbered starting with one. |
||
| 193 | switch ($value['dir']) { |
||
| 194 | case 'asc': |
||
| 195 | $SELECT1 .= ":col_" . $key . " ASC"; |
||
| 196 | break; |
||
| 197 | case 'desc': |
||
| 198 | $SELECT1 .= ":col_" . $key . " DESC"; |
||
| 199 | break; |
||
| 200 | } |
||
| 201 | $ARGS1['col_' . $key] = 1 + $value['column']; |
||
| 202 | } |
||
| 203 | } else { |
||
| 204 | $SELECT1 = " 1 ASC"; |
||
| 205 | } |
||
| 206 | |||
| 207 | if ($length > 0) { |
||
| 208 | $SELECT1 .= " LIMIT :length OFFSET :start"; |
||
| 209 | $ARGS1['length'] = $length; |
||
| 210 | $ARGS1['start'] = $start; |
||
| 211 | } |
||
| 212 | |||
| 213 | $rows = Database::prepare($SELECT1)->execute($ARGS1)->fetchAll(); |
||
| 214 | // Total filtered/unfiltered rows |
||
| 215 | $recordsFiltered = Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
||
| 216 | $recordsTotal = Database::prepare($SELECT2)->execute($ARGS2)->fetchOne(); |
||
| 217 | |||
| 218 | $data = []; |
||
| 219 | foreach ($rows as $row) { |
||
| 220 | $media = Media::getInstance($row->xref, Tree::findById($row->gedcom_id), $row->gedcom); |
||
| 221 | $media_files = $media->mediaFiles(); |
||
| 222 | $media_files = array_map(function (MediaFile $media_file) { |
||
| 223 | return $media_file->displayImage(150, 150, '', []); |
||
| 224 | }, $media_files); |
||
| 225 | $data[] = [ |
||
| 226 | $this->mediaFileInfo($media_folder, $media_path, $row->media_path), |
||
| 227 | implode('', $media_files), |
||
| 228 | $this->mediaObjectInfo($media), |
||
| 229 | ]; |
||
| 230 | } |
||
| 231 | break; |
||
| 232 | |||
| 233 | case 'external': |
||
| 234 | // Filtered rows |
||
| 235 | $SELECT1 = |
||
| 236 | "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS multimedia_file_refn, m_id AS xref, descriptive_title, m_file AS gedcom_id, m_gedcom AS gedcom" . |
||
| 237 | " FROM `##media`" . |
||
| 238 | " JOIN `##media_file` USING (m_id, m_file)" . |
||
| 239 | " WHERE (multimedia_file_refn LIKE 'http://%' OR multimedia_file_refn LIKE 'https://%')" . |
||
| 240 | " AND (multimedia_file_refn LIKE CONCAT('%', :search_1, '%') OR descriptive_title LIKE CONCAT('%', :search_2, '%'))"; |
||
| 241 | $ARGS1 = [ |
||
| 242 | 'search_1' => Database::escapeLike($search), |
||
| 243 | 'search_2' => Database::escapeLike($search), |
||
| 244 | ]; |
||
| 245 | // Unfiltered rows |
||
| 246 | $SELECT2 = |
||
| 247 | "SELECT SQL_CACHE COUNT(*)" . |
||
| 248 | " FROM `##media`" . |
||
| 249 | " JOIN `##media_file` USING (m_id, m_file)" . |
||
| 250 | " WHERE (multimedia_file_refn LIKE 'http://%' OR multimedia_file_refn LIKE 'https://%')"; |
||
| 251 | $ARGS2 = []; |
||
| 252 | |||
| 253 | $order = $request->get('order', []); |
||
| 254 | $SELECT1 .= " ORDER BY "; |
||
| 255 | if ($order) { |
||
| 256 | foreach ($order as $key => $value) { |
||
| 257 | if ($key > 0) { |
||
| 258 | $SELECT1 .= ','; |
||
| 259 | } |
||
| 260 | // Columns in datatables are numbered from zero. |
||
| 261 | // Columns in MySQL are numbered starting with one. |
||
| 262 | switch ($value['dir']) { |
||
| 263 | case 'asc': |
||
| 264 | $SELECT1 .= ":col_" . $key . " ASC"; |
||
| 265 | break; |
||
| 266 | case 'desc': |
||
| 267 | $SELECT1 .= ":col_" . $key . " DESC"; |
||
| 268 | break; |
||
| 269 | } |
||
| 270 | $ARGS1['col_' . $key] = 1 + $value['column']; |
||
| 271 | } |
||
| 272 | } else { |
||
| 273 | $SELECT1 = " 1 ASC"; |
||
| 274 | } |
||
| 275 | |||
| 276 | if ($length > 0) { |
||
| 277 | $SELECT1 .= " LIMIT :length OFFSET :start"; |
||
| 278 | $ARGS1['length'] = $length; |
||
| 279 | $ARGS1['start'] = $start; |
||
| 280 | } |
||
| 281 | |||
| 282 | $rows = Database::prepare($SELECT1)->execute($ARGS1)->fetchAll(); |
||
| 283 | |||
| 284 | // Total filtered/unfiltered rows |
||
| 285 | $recordsFiltered = Database::prepare("SELECT FOUND_ROWS()")->fetchOne(); |
||
| 286 | $recordsTotal = Database::prepare($SELECT2)->execute($ARGS2)->fetchOne(); |
||
| 287 | |||
| 288 | $data = []; |
||
| 289 | foreach ($rows as $row) { |
||
| 290 | $media = Media::getInstance($row->xref, Tree::findById($row->gedcom_id), $row->gedcom); |
||
| 291 | $data[] = [ |
||
| 292 | GedcomTag::getLabelValue('URL', $row->multimedia_file_refn), |
||
| 293 | $media->displayImage(150, 150, '', []), |
||
| 294 | $this->mediaObjectInfo($media), |
||
| 295 | ]; |
||
| 296 | } |
||
| 297 | break; |
||
| 298 | |||
| 299 | case 'unused': |
||
| 300 | // Which trees use this media folder? |
||
| 301 | $media_trees = Database::prepare( |
||
| 302 | "SELECT gedcom_name, gedcom_name" . |
||
| 303 | " FROM `##gedcom`" . |
||
| 304 | " JOIN `##gedcom_setting` USING (gedcom_id)" . |
||
| 305 | " WHERE setting_name='MEDIA_DIRECTORY' AND setting_value = :media_folder AND gedcom_id > 0" |
||
| 306 | )->execute([ |
||
| 307 | 'media_folder' => $media_folder, |
||
| 308 | ])->fetchAssoc(); |
||
| 309 | |||
| 310 | $disk_files = $this->allDiskFiles($media_folder, $media_path, $subfolders, $search); |
||
| 311 | $db_files = $this->allMediaFiles($media_folder, $media_path, $search); |
||
| 312 | |||
| 313 | // All unused files |
||
| 314 | $unused_files = array_diff($disk_files, $db_files); |
||
| 315 | $recordsTotal = count($unused_files); |
||
| 316 | |||
| 317 | // Filter unused files |
||
| 318 | if ($search) { |
||
| 319 | $unused_files = array_filter($unused_files, function ($x) use ($search) { |
||
| 320 | return strpos($x, $search) !== false; |
||
| 321 | }); |
||
| 322 | } |
||
| 323 | $recordsFiltered = count($unused_files); |
||
| 324 | |||
| 325 | // Sort files - only option is column 0 |
||
| 326 | sort($unused_files); |
||
| 327 | $order = $request->get('order', []); |
||
| 328 | if ($order && $order[0]['dir'] === 'desc') { |
||
| 329 | $unused_files = array_reverse($unused_files); |
||
| 330 | } |
||
| 331 | |||
| 332 | // Paginate unused files |
||
| 333 | $unused_files = array_slice($unused_files, $start, $length); |
||
| 334 | |||
| 335 | $data = []; |
||
| 336 | foreach ($unused_files as $unused_file) { |
||
| 337 | $imgsize = getimagesize(WT_DATA_DIR . $media_folder . $media_path . $unused_file); |
||
| 338 | // We can’t create a URL (not in public_html) or use the media firewall (no such object) |
||
| 339 | if ($imgsize === false) { |
||
| 340 | $img = '-'; |
||
| 341 | } else { |
||
| 342 | $url = route('unused-media-thumbnail', ['folder' => $media_folder, 'file' => $media_path . $unused_file, 'w' => 100, 'h' => 100]); |
||
| 343 | $img = '<img src="' . e($url) . '">'; |
||
| 344 | } |
||
| 345 | |||
| 346 | // Is there a pending record for this file? |
||
| 347 | $exists_pending = Database::prepare( |
||
| 348 | "SELECT 1 FROM `##change` WHERE status='pending' AND new_gedcom LIKE CONCAT('%\n1 FILE ', :unused_file, '\n%')" |
||
| 349 | )->execute([ |
||
| 350 | 'unused_file' => Database::escapeLike($unused_file), |
||
| 351 | ])->fetchOne(); |
||
| 352 | |||
| 353 | // Form to create new media object in each tree |
||
| 354 | $create_form = ''; |
||
| 355 | if (!$exists_pending) { |
||
| 356 | foreach ($media_trees as $media_tree) { |
||
| 357 | $create_form .= |
||
| 358 | '<p><a href="#" data-toggle="modal" data-target="#modal-create-media-from-file" data-file="' . e($unused_file) . '" data-tree="' . e($media_tree) . '" onclick="document.getElementById(\'file\').value=this.dataset.file; document.getElementById(\'ged\').value=this.dataset.tree;">' . I18N::translate('Create') . '</a> — ' . e($media_tree) . '<p>'; |
||
| 359 | } |
||
| 360 | } |
||
| 361 | |||
| 362 | $delete_link = '<p><a data-confirm="' . I18N::translate('Are you sure you want to delete “%s”?', e($unused_file)) . '" data-url="' . e(route('admin-media-delete', ['file' => $media_path . $unused_file, 'folder' => $media_folder])) . '" onclick="if (confirm(this.dataset.confirm)) jQuery.post(this.dataset.url, function (){location.reload();})" href="#">' . I18N::translate('Delete') . '</a></p>'; |
||
| 363 | |||
| 364 | $data[] = [ |
||
| 365 | $this->mediaFileInfo($media_folder, $media_path, $unused_file) . $delete_link, |
||
| 366 | $img, |
||
| 367 | $create_form, |
||
| 368 | ]; |
||
| 369 | } |
||
| 370 | break; |
||
| 371 | |||
| 372 | default: |
||
| 373 | throw new BadRequestHttpException; |
||
| 374 | } |
||
| 375 | |||
| 376 | // See http://www.datatables.net/usage/server-side |
||
| 377 | return new JsonResponse([ |
||
| 378 | 'draw' => $request->get('draw'), |
||
| 379 | 'recordsTotal' => $recordsTotal, |
||
| 380 | 'recordsFiltered' => $recordsFiltered, |
||
| 381 | 'data' => $data, |
||
| 382 | ]); |
||
| 710 |