Come feci in occasione del problema nell‘upload delle immagini in Virtuemart, questa volta vi illustro un tricks per risolvere un fastidioso problema che si può avere con il Joomla (solo nelle versioni 1.5.x) quando le cartelle “images” e “media” raggiungono una dimensione e un numero di file/cartelle elevato.
Questo CMS di default (personalmente non ne capisco il motivo) ha abilitata la “ricerca ricorsiva” per tutto ciò che riguarda l’elencazione (listing) di file e cartelle di una path. In questo caso in particolare mi riferisco al componente “com_media” che si occupa della gestione dei contenuti multimediali quali foto e video. Nella pagina principale dell’Amministrazione del Joomla andando su “Gestione Media” si accede ad un interfaccia stile “client ftp” che permette di navigare all’interno delle cartelle “images” e “media” ed eseguire le normali operazioni di cancellazione/modifica/etc su file e cartelle in esse contenute.
Il problema sorge quando il numero di file contenuti in queste due cartelle raggiunge dimensioni tali da non rendere possibile il listing di tutto il contenuto nei 120 secondi di Timeout impostati sul Server (tranne servizi dedicati appostivamente al Joomla i normali Hosting Provider impostano il max_execution_time a 120 secondi). Al termine di tale tempo se l’operazione non è completata, a seconda della configurazione e della versione del WebServer, viene mostrato l’errore “500 Internal Server Error” o “504 Gateway Timeout“. Tradotto in parole povere significa che lo script ha provato ad eseguire l’operazione ma il processo era ancora in corso trascorsi 2 minuti e pertanto è stato bloccato.
Per disabilitare la “ricerca ricorsiva”, quindi, è necessario aprire il file “manager.php” presente nella path:
<root_di_Joomla>/administrator/components/com_media/models/manager.php
e successivamente posizionarsi alle Righe 63 e 102 che appariranno così:
$folders = JFolder::folders($base, '.', true, true);
e modificarle variando il 1° true su false come di seguito:
$folders = JFolder::folders($base, '.', false, true);
Di seguito le prime righe della funzione che viene richiamata che dimostrano che il parametro variato va a disabilitare la ricorsione.
/** * Utility function to read the folders in a folder. * * @param string The path of the folder to read. * @param string A filter for folder names. * @param mixed True to recursively search into sub-folders, or an * integer to specify the maximum depth. * @param boolean True to return the full path to the folders. * @param array Array with names of folders which should not be shown in * the result. * @return array Folders in the given folder. * @since 1.5 */ function folders($path, $filter = '.', $recurse = false, $fullpath = false, $exclude = array('.svn', 'CVS')) { // Initialize variables $arr = array(); // Check to make sure the path valid and clean $path = JPath::clean($path); // Is the path a folder? if (!is_dir($path)) { JError::raiseWarning(21, 'JFolder::folder: ' . JText::_('Path is not a folder'), 'Path: ' . $path); return false; } // read the source directory $handle = opendir($path); while (($file = readdir($handle)) !== false) { if (($file != '.') && ($file != '..') && (!in_array($file, $exclude))) { $dir = $path . DS . $file; $isDir = is_dir($dir); if ($isDir) { // Removes filtered directories if (preg_match("/$filter/", $file)) { if ($fullpath) { $arr[] = $dir; } else { $arr[] = $file; } } if ($recurse) { if (is_integer($recurse)) { $arr2 = JFolder::folders($dir, $filter, $recurse - 1, $fullpath); } else { $arr2 = JFolder::folders($dir, $filter, $recurse, $fullpath); } $arr = array_merge($arr, $arr2); } } } } closedir($handle); asort($arr); return $arr; }
Come spiegato nei commenti della funzione stessa l’impostare su “false” il 3° parametro disabilita la ricorsione evitando il manifestarsi dell’errore di Timeout.
In alternativa è possibile modificare il parametro inserendo un valore numerico intero. Così facendo si indicano quanti livelli deve scendere nella ricerca dei file/cartelle.
Esempio della modifica da apportare se si vuole che la ricerca scenda al massimo di 3 livelli, ossia:
<root_di_Joomla>/images/cartella1/cartella2/cartella3
La riga andrebbe modificata nel seguente modo:
$folders = JFolder::folders($base, '.', 3, true);
Fatto ciò il problema sarò risolto e all’apertura del “com_media” verrà effettuata la ricerca per le sole cartelle “images” e “media” e per il numero di livelli da voi impostato. Tale modifica crea un piccolo problema visivo che, a mio avviso, non è molto rilevante poiché disabilitando la ricorsività dal menu ad albero del “Gestione Media” non si potrà vedere il solito “+” davanti alle cartelle che ne contengono delle altre. Analizzando solo il primo livello delle cartelle non può creare l’albero di navigazione fin da subito e pertanto si aggiornerà man mano che si scende nelle sottocartelle.
Per un problema risolto ritengo sia una piccola perdita.