conf = $conf['batch_download']; $this->data = array( 'id' => 0, 'user_id' => $user['id'], 'date_creation' => '0000-00-00 00:00:00', 'type' => null, 'type_id' => null, 'nb_zip' => 0, 'last_zip' => 0, 'nb_images' => 0, 'total_size' => 0, 'status' => 'new', ); $this->images = array(); // load specific set if (preg_match('#^[0-9]+$#', $set_id)) { $query = ' SELECT id, user_id, date_creation, type, type_id, nb_zip, last_zip, nb_images, total_size, status FROM '.BATCH_DOWNLOAD_TSETS.' WHERE id = '.$set_id.' '.(!is_admin() ? 'AND user_id = '.$this->data['user_id'] : null).' ;'; $result = pwg_query($query); if (pwg_db_num_rows($result)) { $this->data = array_merge( $this->data, pwg_db_fetch_assoc($result) ); // make sur all pictures of the set exist $query = ' DELETE FROM '.BATCH_DOWNLOAD_TIMAGES.' WHERE image_id NOT IN ( SELECT id FROM '.IMAGES_TABLE.' ) ;'; pwg_query($query); $query = ' SELECT image_id, zip FROM '.BATCH_DOWNLOAD_TIMAGES.' WHERE set_id = '.$this->data['id'].' ;'; $this->images = simple_hash_from_query($query, 'image_id', 'zip'); if ( $this->data['status'] != 'done' and count($this->images) != $this->data['nb_images'] ) { $this->updateParam('nb_images', count($this->images)); } } else { throw new Exception(l10n('Invalid dowload set')); } } // create a new set else if ($set_id == 'new') { $this->data['type'] = $type; $this->data['type_id'] = $type_id; $query = ' INSERT INTO '.BATCH_DOWNLOAD_TSETS.'( user_id, date_creation, type, type_id, nb_zip, last_zip, nb_images, total_size, status ) VALUES( '.$this->data['user_id'].', NOW(), "'.$this->data['type'].'", "'.$this->data['type_id'].'", 0, 0, 0, 0, "new" ) ;'; pwg_query($query); $this->data['id'] = pwg_db_insert_id(); $date = pwg_query('SELECT FROM_UNIXTIME(NOW());'); list($this->data['date_creation']) = pwg_db_fetch_row($date); if (!empty($images)) { $this->addImages($images); } } else { trigger_error('BatchDownloader::__construct, invalid input parameter', E_USER_ERROR); } } /** * updateParam * @param: string param name * @param: mixed param value */ function updateParam($name, $value) { $this->data[$name] = $value; pwg_query('UPDATE '.BATCH_DOWNLOAD_TSETS.' SET '.$name.' = "'.$value.'" WHERE id = '.$this->data['id'].';'); } /** * getParam * @param: string param name * @return: mixed param value */ function getParam($name) { return $this->data[$name]; } /** * getImages * @return: array */ function getImages() { return $this->images; } /** * isInSet * @param: int image id * @return: bool */ function isInSet($image_id) { return array_key_exists($image_id, $this->images); } /** * removeImages * @param: array image ids */ function removeImages($image_ids) { if (empty($image_ids) or !is_array($image_ids)) return; foreach ($image_ids as $image_id) { unset($this->images[ $image_id ]); } $query = ' DELETE FROM '.BATCH_DOWNLOAD_TIMAGES.' WHERE set_id = '.$this->data['id'].' AND image_id IN('.implode(',', $image_ids).') ;'; pwg_query($query); $this->updateParam('nb_images', count($this->images)); } /** * addImages * @param: array image ids */ function addImages($image_ids) { if (empty($image_ids) or !is_array($image_ids)) return; $image_ids = array_unique($image_ids); $inserts = array(); foreach ($image_ids as $image_id) { if ($this->isInSet($image_id)) continue; $this->images[ $image_id ] = 0; array_push($inserts, array('set_id'=>$this->data['id'], 'image_id'=>$image_id, 'zip'=>0)); } mass_inserts( BATCH_DOWNLOAD_TIMAGES, array('set_id', 'image_id', 'zip'), $inserts ); $this->updateParam('nb_images', count($this->images)); } /** * clearImages */ function clearImages() { $this->images = array(); $query = ' DELETE FROM '.BATCH_DOWNLOAD_TIMAGES.' WHERE set_id = '.$this->data['id'].' ;'; pwg_query($query); } /** * deleteLastArchive */ function deleteLastArchive() { $zip_path = $this->getArchivePath(); if (file_exists($zip_path)) { unlink($zip_path); } } /** * createNextArchive * @param: bool force all elements in one archive * @return: string zip path or false */ function createNextArchive($force_one_archive=false) { // set already downloaded (we should never be there !) if ( $this->data['status'] == 'done' or $this->data['nb_images'] == 0 ) { trigger_error('BatchDownloader::createNextArchive, the set is empty', E_USER_ERROR); } global $conf; // first zip if ($this->data['last_zip'] == 0) { $this->updateParam('status', 'download'); // limit number of elements if ($this->data['nb_images'] > $this->conf['max_elements']) { $images_ids = array_slice(array_keys($this->images), 0, $this->conf['max_elements']); $this->clearImages(); $this->addImages($images_ids); } $this->getEstimatedArchiveNumber(); $this->updateParam('date_creation', date('Y-m-d H:i:s')); } // get next images of the set $images_to_add = array(); foreach ($this->images as $image_id => $zip_id) { if ($zip_id != 0) continue; // here are already added images array_push($images_to_add, $image_id); } if (count($images_to_add)) { $query = ' SELECT id, name, file, path, filesize FROM '.IMAGES_TABLE.' WHERE id IN ('.implode(',', $images_to_add).') ;'; $images_to_add = hash_from_query($query, 'id'); // open zip $this->updateParam('last_zip', $this->data['last_zip']+1); $zip_path = $this->getArchivePath(); $zip = new myZip($zip_path, isset($conf['batch_download_force_pclzip'])); // add images until size limit is reach, or all images are added $images_added = array(); $total_size = 0; foreach ($images_to_add as $row) { $zip->addFile(PHPWG_ROOT_PATH . $row['path'], $row['id'].'_'.get_filename_wo_extension($row['file']).'.'.get_extension($row['path'])); array_push($images_added, $row['id']); $this->images[ $row['id'] ] = $this->data['last_zip']; $total_size+= $row['filesize']; if ($total_size >= $this->conf['max_size']*1024 and !$force_one_archive) break; } $this->updateParam('total_size', $this->data['total_size'] + $total_size); // archive comment $comment = 'Generated on '.date('r').' with PHP '.PHP_VERSION.' by Piwigo Batch Downloader.'; $comment.= "\n".$conf['gallery_title'].' - '.get_absolute_root_url(); if (!empty($conf['batch_download_comment'])) { $comment.= "\n\n".wordwrap(remove_accents($conf['batch_download_comment']), 60); } $zip->setArchiveComment($comment); $zip->close(); // update database $query = ' UPDATE '.BATCH_DOWNLOAD_TIMAGES.' SET zip = '.$this->data['last_zip'].' WHERE set_id = '.$this->data['id'].' AND image_id IN('.implode(',', $images_added).') ;'; pwg_query($query); // all images added ? if (count($images_to_add) == count($images_added)) { $this->updateParam('status', 'done'); } // over estimed if ( $this->data['status'] == 'done' and $this->data['last_zip'] < $this->data['nb_zip'] ) { $this->updateParam('nb_zip', $this->data['last_zip']); } // under estimed else if ( $this->data['last_zip'] == $this->data['nb_zip'] and $this->data['status'] != 'done' ) { $this->updateParam('nb_zip', $this->data['last_zip']+1); } return $zip_path; } else { return false; } } /** * getEstimatedTotalSize * @return: int */ function getEstimatedTotalSize() { if ($this->data['status'] == 'done') return $this->data['total_size']; if ($this->data['nb_images'] == 0) return 0; $image_ids = array_slice(array_keys($this->images), 0, $this->conf['max_elements']); $query = ' SELECT SUM(filesize) AS total FROM '.IMAGES_TABLE.' WHERE id IN ('.implode(',', $image_ids).') ;'; list($total) = pwg_db_fetch_row(pwg_query($query)); return $total; } /** * getEstimatedArchiveNumber * @return: int */ function getEstimatedArchiveNumber() { $nb_zip = ceil( $this->getEstimatedTotalSize() / ($this->conf['max_size']*1024) ); $this->updateParam('nb_zip', $nb_zip); return $nb_zip; } /** * getDownloadList * @return: string html */ function getDownloadList($url='') { if ($this->data['nb_images'] == 0) { return ''.l10n('No archive').''; } $root_url = get_root_url(); $out = ''; for ($i=1; $i<=$this->data['nb_zip']; $i++) { $out.= '