diff --git a/VERSIONS_WIP/38660 b/VERSIONS_WIP/38660 new file mode 100644 index 0000000000000000000000000000000000000000..ff12aae0d643e920144c597e7622fb3366fcd05b --- /dev/null +++ b/VERSIONS_WIP/38660 @@ -0,0 +1 @@ + - ticket #38660 : (9/40) Fiche Bibliothèque : Monter le poids de l'image à 250 Ko \ No newline at end of file diff --git a/application/modules/admin/controllers/BibController.php b/application/modules/admin/controllers/BibController.php index b34b17c88e2e029b888f495fc626cc9d8feb9427..cca5714a82a2eef60ff72ba671641e66b1dd0532 100644 --- a/application/modules/admin/controllers/BibController.php +++ b/application/modules/admin/controllers/BibController.php @@ -59,10 +59,6 @@ class Admin_BibController extends ZendAfi_Controller_Action { } - protected function _doAfterSave($model) { - $model->receiveFile('photo'); - } - protected function _canEdit($model) { return !$this->accessForbidden(); } @@ -105,100 +101,6 @@ class Admin_BibController extends ZendAfi_Controller_Action { } - public function photoAction() { - $viewRenderer = $this->getHelper('ViewRenderer'); - $viewRenderer->setNoRender(); - - // Parametres et adresse du fichier - $id_bib = (int)$this->_request->getParam('id'); - $img = "/userfiles/photobib/photoBib".$id_bib.".jpg"; - $url_img = $this->view->url(['module'=>'admin', - 'controller'=>'bib', - 'action'=>'getimage', - 'id'=>$id_bib]); - $adresse_img = getcwd().$img; - if (!file_exists($adresse_img)) - $url_img = BASE_URL."/userfiles/photobib/photoVide.jpg"; - - $html = '<body style="background-color:#f0f0f0;overflow:hidden">'; - $html .= '<link rel="stylesheet" type="text/css" media="screen" href="'.URL_ADMIN_CSS.'global.css" />'; - $html .= '<div>'; - - - if ($_FILES["photo"]) { - $fic = $_FILES["photo"]; - $html .= $this->view->_("Fichier photo : %s", $fic["name"] . BR); - if($fic["error"] > 0) { - if(!$fic["name"]) { - $erreur = $this->view->_("Vous devez sélectionner une photo en cliquant sur le bouton : parcourir"); - } elseif(!$fic["size"]) { - $erreur = $this->view->_("Le fichier que vous avez sélectionné est vide."); - } else { - $erreur = $this->view->_('Erreur au téléchargement du fichier : L\'image que vous essayez de télécharger est trop volumineuse ou inaccessible.'); - } - - } else { - $ext=strToLower(strRight($fic["type"],3)); - $taille=(int)($fic["size"]/1024); - if ($ext !="jpg" and $ext != "peg") { - $erreur = $this->view->_("La photo que vous avez sélectionnée doit être de type : 'image/jpg' et pas de type : %s", $fic["type"]); - } elseif($taille > 100 ) { - $erreur = $this->view->_("La photo que vous avez sélectionnée est trop volumiseuse : %d ko", $taille); - } else { - if(move_uploaded_file($fic['tmp_name'], $adresse_img)) { - $html .= "<script>document.location.replace('".BASE_URL."/admin/bib/photo?id=".$id_bib."&upload=1')</script>"; - } else { - $erreur = $this->view->_("Erreur au transfert du fichier vers userfiles"); - } - } - } - - if($erreur) { - $html .= BR.'<span>'.$erreur.'</span>'; - $html .= BR.BR.'<center><input type="button" class="bouton" value="'.$this->view->_("Retour").'" onclick="document.location.replace(\''.BASE_URL.'/admin/bib/photo?id='.$id_bib.'\')">'; - } - - } else { - if ($_REQUEST["upload"]==1) { - $html.='<script>window.top.document.getElementById("photo").value="'.$img.'";</script>'; - } - - $html .= '<form name="form" action="'.BASE_URL.'/admin/bib/photo?id='.$id_bib.'" enctype="multipart/form-data" method="post">'; - $html .= '<table><tr>'; - $html .= '<td width="190px"><img src="'.$url_img.'" width="180px" height="140px"></td>'; - $html .= '<td style=padding-left:10px"><span style="font-size:12px">'.$this->view->_('NB : l\'image doit être de type ".jpg", avoir une taille inférieure à 100 ko et des dimensions se rapprochant de 180 / 140 pixels').'</span><br/><br/>'; - $html .= '<center><input type="file" name="photo" size="40" enctype="multipart/form-data">'; - $html .= '<br/><br/><input type="submit" class="bouton" value="'.$this->view->_('Envoyer la photo sur le serveur').'"></td>'; - $html .= '</tr></table></form>'; - } - - $html .= '</div>'; - $html .= '<script>document.body.setAttribute("bgColor ","#f0f0f0"))</script>'; - - $this->getResponse()->setHeader('Content-Type', 'text/html;charset=utf-8'); - $this->getResponse()->setHeader('pragma', 'no-cache'); - $this->getResponse()->setBody($html); - } - - - public function getimageAction() { - $id_bib = (int)$this->_request->getParam('id'); - $img = "/userfiles/photobib/photoBib".$id_bib.".jpg"; - $adresse_img=getcwd().$img; - if (!file_exists($adresse_img)) - $adresse_img = getcwd()."/userfiles/photobib/photoVide.jpg"; - - $handle = fopen($adresse_img,"rb"); - $data = fread($handle, filesize($adresse_img)); - fclose($handle); - - header("Content-type: image/jpg"); - header("pragma: no-cache"); - print($data); - exit; - } - - public function localisationsAction() { $cls_loc = new Class_Localisation(); $id_bib = (int)$this->_request->getParam('id_bib'); diff --git a/application/modules/opac/controllers/BibController.php b/application/modules/opac/controllers/BibController.php index 5150bb8998511f00d5772f0872b247d525af5851..73c647e6dd04e1fff4e2ae00dc6ff182dd7d26ad 100644 --- a/application/modules/opac/controllers/BibController.php +++ b/application/modules/opac/controllers/BibController.php @@ -18,9 +18,8 @@ * along with BOKEH; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -////////////////////////////////////////////////////////////////////////////////////////// -// OPAC3 - Controleur localisations -////////////////////////////////////////////////////////////////////////////////////////// + + class BibController extends ZendAfi_Controller_Action { private $_pathImg = "./public/admin/images/"; @@ -236,23 +235,6 @@ class BibController extends ZendAfi_Controller_Action { } - function photobibAction() { - $id_bib = (int)$this->_request->getParam('id_bib'); - $img="/userfiles/photobib/photoBib".$id_bib.".jpg"; - $adresse_img=getcwd().$img; - - if(! file_exists($adresse_img)) $adresse_img=getcwd()."/userfiles/photobib/photoVide.jpg"; - $handle=fopen($adresse_img,"rb"); - $data=fread ($handle, filesize($adresse_img)); - fclose($handle); - - header("Content-type: image/jpg"); - header("pragma: no-cache"); - print($data); - exit; - } - - function giveInfoBulle($id_bib) { $class_bib = new Class_Bib(); $bib = $class_bib->getBibById($id_bib); diff --git a/library/Class/Bib.php b/library/Class/Bib.php index bf575e9c5136b9c18134f81828ba2b4359a4e50c..a40508648524d3eca70b288164ae8440fcd7d89c 100644 --- a/library/Class/Bib.php +++ b/library/Class/Bib.php @@ -155,104 +155,117 @@ class BibLoader extends Storm_Model_Loader { class Class_Bib extends Storm_Model_Abstract { - use Trait_PermissionTargetable, Trait_UploadFile, Trait_CustomFields, Trait_JsonLibrary, Trait_Translator; - - const V_INVISIBLE = 0; - const V_NODATA = 1; - const V_DATA = 2; - - const BASE_PATH = 'photobib/'; - const THUMBS_PATH = 'thumbs/'; - const THUMB_PREFIX = 'thumb_'; - private $_dataBaseError = "Problème d'accès à la base de données"; - private $statut_bib; - - protected $_loader_class = 'BibLoader'; - protected $_table_name = 'bib_c_site'; - protected $_table_primary = 'ID_SITE'; - protected $_has_many = ['profils' => ['model' => 'Class_Profil', - 'role' => 'bib', - 'dependents' => 'delete'], - - 'users' => ['model' => 'Class_Users', - 'role' => 'bib', - 'dependents' => 'delete'], - - 'article_categories' => ['model' => 'Class_ArticleCategorie', - 'role' => 'bib', - 'scope' => ['ID_CAT_MERE' => 0], - 'order' => 'libelle', - 'dependents' => 'delete'], + use + Trait_PermissionTargetable, + Trait_CustomFields, + Trait_Translator, + Trait_StaticFileSystem, + Trait_JsonLibrary; - 'articles' => ['through' => 'article_categories'], + const + V_INVISIBLE = 0, + V_NODATA = 1, + V_DATA = 2, + UPLOAD_MAX_SIZE = 250, + BASE_PATH = 'photobib/', + THUMB_PREFIX = 'thumb_'; + protected static $_default_image_factory; - 'sitotheque_categories' => ['model' => 'Class_SitothequeCategorie', - 'role' => 'bib', - 'scope' => ['ID_CAT_MERE' => 0], - 'order' => 'libelle', - 'dependents' => 'delete'], + private + $_dataBaseError = "Problème d'accès à la base de données", + $statut_bib; - 'sitotheques' => ['through' => 'sitotheque_categories'], + protected + $_loader_class = 'BibLoader', + $_table_name = 'bib_c_site', - 'rss_categories' => ['model' => 'Class_RssCategorie', - 'role' => 'bib', - 'scope' => ['ID_CAT_MERE' => 0], - 'order' => 'libelle', - 'dependents' => 'delete'], + $_table_primary = 'ID_SITE', - 'feeds' => ['through' => 'rss_categories'], + $_has_many = ['profils' => ['model' => 'Class_Profil', + 'role' => 'bib', + 'dependents' => 'delete'], + 'users' => ['model' => 'Class_Users', + 'role' => 'bib', + 'dependents' => 'delete'], - 'ouvertures' => ['model' => 'Class_Ouverture', + 'article_categories' => ['model' => 'Class_ArticleCategorie', 'role' => 'bib', - 'order' => ['jour', 'debut_matin'], + 'scope' => ['ID_CAT_MERE' => 0], + 'order' => 'libelle', 'dependents' => 'delete'], - 'exemplaires' => ['model' => 'Class_Exemplaire', - 'role' => 'bib', - 'dependents' => 'delete'], - 'localisations' => ['model' => 'Class_Localisation', + 'articles' => ['through' => 'article_categories'], + + + 'sitotheque_categories' => ['model' => 'Class_SitothequeCategorie', 'role' => 'bib', - 'order' => 'libelle'], - 'plans' => ['model' => 'Class_Plan', - 'role' => 'bib', - 'order' => 'libelle']]; + 'scope' => ['ID_CAT_MERE' => 0], + 'order' => 'libelle', + 'dependents' => 'delete'], - protected $_belongs_to = ['zone' => ['model' => 'Class_Zone', + 'sitotheques' => ['through' => 'sitotheque_categories'], + + + 'rss_categories' => ['model' => 'Class_RssCategorie', 'role' => 'bib', - 'referenced_in' => 'id_zone'], - - 'int_bib' => ['model' => 'Class_IntBib', - 'role' => 'bib', - 'referenced_in' => 'id_site']]; - - protected $_default_attribute_values = ['visibilite' => 0, - 'libelle' => '', - 'id_zone' => 0, - 'ville' => '', - 'mail' => '', - 'telephone' => '', - 'aff_zone' => '', - 'interdire_resa' => 0, - 'google_map' => '', - 'photo' => '', - 'redmine_login' => '', - 'redmine_password' => '', - 'redmine_api_key' => '', - 'cp' => '', - 'lien_carto' => '', - 'horaire' => '', - 'inscription' => '', - 'pret' => '', - 'annexe' => '', - 'procure' => '', - 'closed_on_holidays' => true]; - - - protected $_translate; - protected $_fixed_id = true; + 'scope' => ['ID_CAT_MERE' => 0], + 'order' => 'libelle', + 'dependents' => 'delete'], + + 'feeds' => ['through' => 'rss_categories'], + + + 'ouvertures' => ['model' => 'Class_Ouverture', + 'role' => 'bib', + 'order' => ['jour', 'debut_matin'], + 'dependents' => 'delete'], + + 'exemplaires' => ['model' => 'Class_Exemplaire', + 'role' => 'bib', + 'dependents' => 'delete'], + 'localisations' => ['model' => 'Class_Localisation', + 'role' => 'bib', + 'order' => 'libelle'], + 'plans' => ['model' => 'Class_Plan', + 'role' => 'bib', + 'order' => 'libelle']], + + $_belongs_to = ['zone' => ['model' => 'Class_Zone', + 'role' => 'bib', + 'referenced_in' => 'id_zone'], + + 'int_bib' => ['model' => 'Class_IntBib', + 'role' => 'bib', + 'referenced_in' => 'id_site']], + + $_default_attribute_values = ['visibilite' => 0, + 'libelle' => '', + 'id_zone' => 0, + 'ville' => '', + 'mail' => '', + 'telephone' => '', + 'aff_zone' => '', + 'interdire_resa' => 0, + 'google_map' => '', + 'photo' => '', + 'redmine_login' => '', + 'redmine_password' => '', + 'redmine_api_key' => '', + 'cp' => '', + 'lien_carto' => '', + 'horaire' => '', + 'inscription' => '', + 'pret' => '', + 'annexe' => '', + 'procure' => '', + 'closed_on_holidays' => true], + + $_fixed_id = true, + $file_uploaded = false, + $_uploadHandler; public function __construct() { parent::__construct(); @@ -405,20 +418,6 @@ class Class_Bib extends Storm_Model_Abstract { return $errorMessage; } - //---------------------------------------------------------------------------- - // Controle de suppression d'une bibliothèque - //---------------------------------------------------------------------------- - function isBibDeletable() { - $id_bib = $this->getId(); - $cms=fetchOne("Select count(*) from cms_categorie where ID_SITE=$id_bib"); - $rss=fetchOne("Select count(*) from rss_categorie where ID_SITE=$id_bib"); - $sito=fetchOne("Select count(*) from sito_categorie where ID_SITE=$id_bib"); - $user=fetchOne("Select count(*) from bib_admin_users where ID_SITE=$id_bib"); - $ex=fetchOne("select count(*) from exemplaires where id_bib=$id_bib"); - - if($cms+$rss+$sito+$user+$ex > 0) return false; - else return true; - } // ---------------------------------------------------------------- // Mise à jour de la table int-bib dans cosmogramme @@ -485,12 +484,10 @@ class Class_Bib extends Storm_Model_Abstract { } } - // Rend l'image si trouve, sinon rend l'url - public function getImageBib($id_bib, $taille = "auto") - { - $img = URL_ADMIN_IMG .'bib/bib_'.$id_bib.'.jpg'; - if (file_exists( '..'.$img)) return '<img src="'.$img.'" border="0" style="width:'.$taille.';"/>'; - return 'Pas d\'image'; + + public function getFilePath() { + return ($this->getFileName() == $this->getFile()) ? + $this->getBasePath().$this->getFile() : $this->getFile(); } @@ -499,19 +496,12 @@ class Class_Bib extends Storm_Model_Abstract { } - public function getThumbnailUrl() { - if ('' == $this->getFile()) - return ''; - - return $this->getBaseUrl() . self::THUMB_PREFIX; - } - - public function getThumbnailPath() { + public function getThumbnailPath() { return $this->getBasePath() . self::THUMB_PREFIX . $this->getFile(); } - public function getBase($prefix) { + public function getBase($prefix) { return str_replace('//', '/', $prefix.'/'.self::BASE_PATH.'/'); } @@ -551,6 +541,7 @@ class Class_Bib extends Storm_Model_Abstract { return $dict; } + private function treeConfig($type) { // liste des tables, classes, ... pour chaque type de données $configs = array( @@ -655,10 +646,6 @@ class Class_Bib extends Storm_Model_Abstract { } - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// FONCTIONS DE MISES A JOUR -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Ajouter une Bib public function addBib($data) { @@ -688,6 +675,7 @@ class Class_Bib extends Storm_Model_Abstract { $this->getVisibilite()); } + // Modifier une bibliotheque public function editBib($data, $id_bib) { @@ -764,6 +752,118 @@ class Class_Bib extends Storm_Model_Abstract { } + public function isReceivedFile() { + if (!$this->_isFileInRequest('photo')) + return true; + if ($this->file_uploaded) + return $this->file_uploaded; + return $this->file_uploaded=$this->receiveFile(); + } + + + protected function _isFileInRequest($name) { + if (!array_key_exists($name, $_FILES)) + return false; + return true; + } + + + public static function setDefaultImageFactory($factory) { + static::$_default_image_factory = $factory; + } + + + public static function getImageFactory($file) { + return isset(static::$_default_image_factory) + ? static::$_default_image_factory + : new Imagick($file); + } + + + public function validate() { + $this->checkAttribute('photo', + $this->isReceivedFile('photo'), + implode(',',array_unique($this->getErrors()))); + } + + + public function receiveFile() { + $oldFile = $this->getPhoto(); + $filename = ($this->getFileName()); + $path = ($filename==$oldFile) ? + $this->getBasePath().$oldFile : $oldFile; + + $to_delete = [$path, $this->getBasePath().'thumb_'.$filename]; + $on_update = function($old_file, $new_file) use ($to_delete) { + if ($old_file && $old_file != $new_file) + foreach($to_delete as $item) + $this->getFileSystem()->unlink($item); + + $this->createThumbnail(); + + return true; + }; + + $handler = $this->getUploadHandler('photo', static::UPLOAD_MAX_SIZE) + ->setAllowedExtensions(['jpg', 'gif', 'png', 'jpeg']); + + return (new Class_FileProperty($this, 'photo', $handler, $on_update)) + ->receive(); + } + + + public function createThumbnail() { + if ('' == $this->getFile()) + return true; + + try { + $image = self::getImageFactory($this->getBasePath() . $this->getFile()); + $image->thumbnailImage(160, 0); + + if (!$image->writeImage($this->getThumbnailPath())) { + $this->addError('Erreur lors de l\'enregistrement de la vignette'); + return false; + } + + return true; + + } catch (Exception $e) { + $this->addError('Erreur lors de la création de la vignette ' + . (string)$e->getMessage()); + return false; + } + } + + + public function getFileName() { + $path=explode('/',$this->getFile()); + return end($path); + } + + + public function getBasePath() { + return $this->getBase(USERFILESPATH); + } + + + public function getUploadHandler($name,$limit_size_in_ko=-1) { + if (null === $this->_uploadHandler) { + $this->_uploadHandler = Class_Upload::newInstanceFor($name) + ->setBaseName($this->getId()) + ->setBasePath($this->getBasePath()) + ->setMaxSize($limit_size_in_ko); + } + + return $this->_uploadHandler; + } + + + public function setUploadMover($name, $mover) { + $this->getUploadHandler($name,static::UPLOAD_MAX_SIZE)->setUploadMover($mover); + return $this; + } + + public function getFacet() { return Class_IntBib::CODE_FACETTE . $this->getIdSite(); } diff --git a/library/Class/FileProperty.php b/library/Class/FileProperty.php index 48d3ba7c65bf2cab2fa8149b90add4658bce1325..ee242747e27124331760d246df8f8c59da2c3f86 100644 --- a/library/Class/FileProperty.php +++ b/library/Class/FileProperty.php @@ -56,10 +56,14 @@ class Class_FileProperty { return $this->_onUpdate($old_file); } + public function hasErrorCodeOnFile() { + return array_key_exists('error', $_FILES[$this->_name]) + && 4 !== $_FILES[$this->_name]['error']; + } protected function _isInRequest() { return array_key_exists($this->_name, $_FILES) - && 0 !== $_FILES[$this->_name]['size']; + && $this->hasErrorCodeOnFile(); } @@ -69,8 +73,8 @@ class Class_FileProperty { return false; } - return $this->_setValue($this->_upload_handler->getSavedFileName()) - ->save(); + return $this->_setValue($this->_upload_handler->getSavedFileName()); + } diff --git a/library/Class/FileWriter.php b/library/Class/FileWriter.php index c76708466cb8ff6b426f39604935476d5ba64fe7..c00de4d818b0dc313dc9787979e80b3b7e6a1ed7 100644 --- a/library/Class/FileWriter.php +++ b/library/Class/FileWriter.php @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ class Class_FileWriter { @@ -35,7 +35,7 @@ class Class_FileWriter { public function mkdir($directory_name) { return mkdir($directory_name,0777,true); - + } public function getContents($path) { @@ -43,6 +43,10 @@ class Class_FileWriter { } + public function moveUploadedFile($source,$destination) { + return move_uploaded_file($source,$destination); + } + } ?> \ No newline at end of file diff --git a/library/Class/Upload.php b/library/Class/Upload.php index a09960a8045d9ae40d380e3beb9505c4e67e4b96..1ad7a6ece4a080d3893d531a9c753c5a01724ede 100644 --- a/library/Class/Upload.php +++ b/library/Class/Upload.php @@ -16,12 +16,12 @@ * * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ class Class_Upload { use Trait_Translator; - + /** @var string */ protected $_name; @@ -48,7 +48,9 @@ class Class_Upload { /** @var array */ protected $_allowedExtensions = []; - + + protected $max_size=-1; + /** * @param string $inputName @@ -58,7 +60,17 @@ class Class_Upload { return new self($inputName); } + public function getPhpFileUploadErrors() { + return [ + 1 => $this->_('Le fichier dépasse la taille limite (upload_max_filesize de php.ini)'), + 2 => $this->_('La taille du fichier ne doit pas excéder '.$this->max_size.'ko'), // MAX_FILE_SIZE directive + 3 => $this->_('Le fichier n\'a pu être téléchargé complètement'), + 6 => $this->_('Impossible de télécharger la photo , le répertoire temporaire n\'existe pas'), + 7 => $this->_('Impossible d\`écrire le fichier sur le disque'), + 8 => $this->_('Une extension PHP a stoppé le téléchargement du fichier') + ]; + } /** * @param string $inputName */ @@ -85,7 +97,7 @@ class Class_Upload { } - /** + /** * @param array $extensions * @return Class_Upload */ @@ -252,6 +264,10 @@ class Class_Upload { return $this->_folderManager; } + public function setMaxSize($size_in_ko) { + $this->max_size=$size_in_ko; + return $this; + } /** * @param string $path @@ -262,6 +278,13 @@ class Class_Upload { } + + public function hasErrorCodeOnFile() { + return array_key_exists('error', $_FILES[$this->_name]) + && array_key_exists($_FILES[$this->_name]['error'],$this->getPhpFileUploadErrors()); + } + + /** @return bool */ public function validate() { if ('' == $this->_name) { @@ -273,14 +296,30 @@ class Class_Upload { $this->setError($this->_('Transfert impossible, champ de fichier introuvable')); return false; } + if ($this->hasErrorCodeOnFile()) { + $this->setError($this->getPhpFileUploadErrors()[$_FILES[$this->_name]['error']]); + return false; + } - if (0 == (int)$_FILES[$this->_name]['size']) { + $file_size=isset($_FILES[$this->_name]['size']) ? (int)$_FILES[$this->_name]['size'] : -1; + + if (0 == $file_size) { $this->setError($this->_('Le fichier était vide ou un problème réseau est survenu')); return false; } if (!$this->_ensureDirectory($this->getBasePath())) { - $this->setError('Transfert impossible, le répertoire de destination n\'a pas pu être créé.'); + $this->setError($this->_('Transfert impossible, le répertoire de destination n\'a pas pu être créé.')); + return false; + } + + if($this->max_size>0 && ((int)$this->max_size*1000) < $file_size){ + $this->setError($this->_('La taille du fichier ne doit pas excéder '.$this->max_size.'ko')); + return false; + } + + if (!array_key_exists('name',$_FILES[$this->_name])) { + $this->setError($this->_('Le fichier n\'a pas de nom')); return false; } diff --git a/library/Class/UploadMover/HttpPost.php b/library/Class/UploadMover/HttpPost.php index e4bb5991d907c41048471bb1b268fabd8543f4bd..37798ac9c50184c605c197a901672705d08e175b 100644 --- a/library/Class/UploadMover/HttpPost.php +++ b/library/Class/UploadMover/HttpPost.php @@ -16,11 +16,12 @@ * * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ class Class_UploadMover_HttpPost extends Class_UploadMover_Abstract { - use Trait_Translator; + use Trait_Translator, + Trait_StaticFileWriter; /** * @codeCoverageIgnore * @param string $source @@ -28,7 +29,7 @@ class Class_UploadMover_HttpPost extends Class_UploadMover_Abstract { * @return bool */ public function moveTo($source, $destination) { - if (!move_uploaded_file($source, $destination)) { + if (!$this->getFileWriter()->moveUploadedFile($source, $destination)) { $this->setError(sprintf($this->_('Impossible d\'écrire le fichier sur le serveur au chemin [%s]'), $destination)); return false; } diff --git a/library/Trait/UploadFile.php b/library/Trait/UploadFile.php deleted file mode 100644 index 68ef961ceedc9e72eeb2fd655e45ae95463d61b0..0000000000000000000000000000000000000000 --- a/library/Trait/UploadFile.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php -/** - * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved. - * - * BOKEH is free software; you can redistribute it and/or modify - * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by - * the Free Software Foundation. - * - * There are special exceptions to the terms and conditions of the AGPL as it - * is applied to this software (see README file). - * - * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. - * - * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE - * along with BOKEH; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -trait Trait_UploadFile { - use Trait_StaticFileSystem; - - public function receiveFile($attribute_name) { - if (!$this->_isFileInRequest($attribute_name)) - return true; - - $oldFile = $this->getFile(); - if (!$this->_uploadFile($attribute_name, - ['jpg', 'gif', 'png', 'jpeg', 'bro'], - [$this->getBasePath() . $oldFile, - $this->getBasePath() . 'thumb_'.$oldFile])) - return false; - - return $this->createThumbnail(); - } - - - protected function _uploadFile($name, $extensions, $delete_files) { - $upload = $this - ->getUploadHandler($name) - ->setAllowedExtensions($extensions); - - if (!$upload->receive()) { - $this->addError($upload->getError()); - return false; - } - - $oldFile = $this->_get($name); - $this->_set($name, $upload->getSavedFileName())->save(); - $this->deleteOldFile($delete_files,$oldFile,$name); - return true; - } - - - protected function deleteOldFile($delete_files,$oldFile,$name) { - if (('' != $oldFile) && ($oldFile != $this->_get($name))) { - foreach ($delete_files as $delete_file) - $this->getFileSystem()->unlink($delete_file); - } - } - - - protected function _isFileInRequest($name) { - if (!array_key_exists($name, $_FILES)) - return false; - return (0 !== $_FILES[$name]['size']); - } - - - public function getUploadHandler($name) { - if (null === $this->_uploadHandler) { - $this->_uploadHandler = Class_Upload::newInstanceFor($name) - ->setBaseName($this->getId()) - ->setBasePath($this->getBasePath()); - } - - return $this->_uploadHandler; - } - - - public function createThumbnail() { - if ('' == $this->getFile()) - return true; - - try { - $image = new Imagick($this->getBasePath() . $this->getFile()); - $image->thumbnailImage(160, 0); - - if (!$image->writeImage($this->getThumbnailPath())) { - $this->addError('Erreur lors de l\'enregistrement de la vignette'); - return false; - } - - return true; - - } catch (Exception $e) { - $this->addError('Erreur lors de la création de la vignette ' - . (string)$e->getMessage()); - return false; - } - } - - - public function getBasePath() { - return $this->getBase(USERFILESPATH); - } -} \ No newline at end of file diff --git a/library/ZendAfi/Form/Admin/Library.php b/library/ZendAfi/Form/Admin/Library.php index 00021937df2a0bbb8fa68ff0a91af17ef8970964..37527391d68036263ca4c8bff9bf1918996da8fc 100644 --- a/library/ZendAfi/Form/Admin/Library.php +++ b/library/ZendAfi/Form/Admin/Library.php @@ -78,7 +78,7 @@ class ZendAfi_Form_Admin_Library extends ZendAfi_Form { 'allowEmpty' => false]) ->addElement('image', 'photo', - ['label' => $this->_('Photo (taille inférieure à 100 ko et dimensions prochent de 180px /140px)'), + ['label' => $this->_('Photo (taille inférieure à 250 ko et dimensions prochent de 180px /140px)'), 'escape' => false, 'basePath' => USERFILESPATH.'/'.Class_Bib::BASE_PATH.'/', 'baseUrl' => USERFILESURL.'/'.Class_Bib::BASE_PATH.'/', diff --git a/library/ZendAfi/View/Helper/BibView.php b/library/ZendAfi/View/Helper/BibView.php index b8e10e1609fb082fd1a6a9173a35c9e80419f200..4ba9d03ba95f89134d00c4c1beb0358c32a0c5ef 100644 --- a/library/ZendAfi/View/Helper/BibView.php +++ b/library/ZendAfi/View/Helper/BibView.php @@ -62,19 +62,11 @@ class ZendAfi_View_Helper_BibView extends ZendAfi_View_Helper_BaseHelper { protected function _renderPicture() { - $img = (trim($this->bib->getPhoto()) !== '') ? $this->_getImage() : ''; $map = (trim($this->bib->getGoogleMap()) !== '') ? $this->_getMap() : ''; - return $this->_tag('dd',$img . $map, ['class' => 'picture']); - } - - - protected function _getImage() { - $url = $this->view->url(['controller' => 'bib', - 'action' => 'photobib', - 'id_bib' => $this->bib->getIdSite()], null, true); - - return $this->view->tagImg($url, ['class' => 'bibview_image']); + return $this->_tag('dd', + $this->view->libraryPicture($this->bib) . $map, + ['class' => 'picture']); } diff --git a/library/ZendAfi/View/Helper/LibraryPicture.php b/library/ZendAfi/View/Helper/LibraryPicture.php new file mode 100644 index 0000000000000000000000000000000000000000..b80e89be053e1f302d2c38fda0bfb6e52e67e986 --- /dev/null +++ b/library/ZendAfi/View/Helper/LibraryPicture.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +class ZendAfi_View_Helper_LibraryPicture extends ZendAfi_View_Helper_BaseHelper { + public function libraryPicture($library) { + if (!$picture = $library->getPhoto()) + return ''; + + $url = (false === strpos($picture, 'userfiles')) + ? USERFILESURL . Class_Bib::BASE_PATH . $picture + : BASE_URL . $picture; + + return $this->view->tagImg($url, + ['class' => 'bibview_image']); + } +} + +?> \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/RenderLibrary.php b/library/ZendAfi/View/Helper/RenderLibrary.php index 6ed79fe5467122a3eaff3b09266e61503d6c629d..084c1960819be53aeb874a605048837b6a826ab6 100644 --- a/library/ZendAfi/View/Helper/RenderLibrary.php +++ b/library/ZendAfi/View/Helper/RenderLibrary.php @@ -21,16 +21,15 @@ class ZendAfi_View_Helper_RenderLibrary extends ZendAfi_View_Helper_BaseHelper { - - protected $preferences; - protected $library; - - protected $_fields = - [Class_Systeme_ModulesAccueil_Library::FIELD_OPEN_CLOSE => 'renderOpenClose', - Class_Systeme_ModulesAccueil_Library::FIELD_OPENING_HOURS => 'renderOpeningHours', - Class_Systeme_ModulesAccueil_Library::FIELD_ADDRESS => 'renderAddress', - Class_Systeme_ModulesAccueil_Library::FIELD_PHONE => 'renderPhone', - Class_Systeme_ModulesAccueil_Library::FIELD_MAIL => 'renderMail']; + protected + $preferences, + $library, + $_fields = [ + Class_Systeme_ModulesAccueil_Library::FIELD_OPEN_CLOSE => 'renderOpenClose', + Class_Systeme_ModulesAccueil_Library::FIELD_OPENING_HOURS => 'renderOpeningHours', + Class_Systeme_ModulesAccueil_Library::FIELD_ADDRESS => 'renderAddress', + Class_Systeme_ModulesAccueil_Library::FIELD_PHONE => 'renderPhone', + Class_Systeme_ModulesAccueil_Library::FIELD_MAIL => 'renderMail']; public function renderLibrary($library, $preferences) { @@ -135,16 +134,10 @@ class ZendAfi_View_Helper_RenderLibrary extends ZendAfi_View_Helper_BaseHelper { protected function renderPicture() { - if (!$this->library->getPhoto()) + if (!$content = $this->view->libraryPicture($this->library)) return ''; - $url = $this->view->url(['module' => 'opac', - 'controller' => 'bib', - 'action' => 'photobib', - 'id_bib' => $this->library->getIdSite()], null, true); - - return $this->_renderField($this->view->tagImg($url, ['class' => 'bibview_image']), - 'field-picture'); + return $this->_renderField($content, 'field-picture'); } diff --git a/tests/application/modules/admin/controllers/BibControllerTest.php b/tests/application/modules/admin/controllers/BibControllerTest.php index b67d3b2b2775ab730a30c4a6d1ce0102269ca70c..1c1523d37d48e4378b41f2c773a216c9209fbc14 100644 --- a/tests/application/modules/admin/controllers/BibControllerTest.php +++ b/tests/application/modules/admin/controllers/BibControllerTest.php @@ -21,7 +21,8 @@ require_once 'AbstractControllerTestCase.php'; abstract class BibControllerTestCase extends AbstractControllerTestCase { - protected $_storm_default_to_volatile = true; + protected + $_storm_default_to_volatile = true; public function setUp() { parent::setUp(); @@ -424,11 +425,11 @@ class BibControllerWithAdminBibEditAnnecyPostTest extends BibControllerWithAdmin + class BibControllerWithAdminBibEditAnnecyPostWithVisibiliteZeroTest extends BibControllerWithAdminBibTestCase { public function setUp() { parent::setUp(); - $this->fixture('Class_IntBib', ['id' => 2]); @@ -440,11 +441,6 @@ class BibControllerWithAdminBibEditAnnecyPostWithVisibiliteZeroTest extends BibC ['id' => 5, 'id_bib' => 2]); - $_FILES['image'] = ['size' => 100, - 'name' => 'photo', - 'tmp_name' => 'toto.png', - 'error' => 4]; - $this->postDispatch('admin/bib/edit/id/2', ['libelle' => 'Bonlieu', 'responsable' => 'Géraldine', @@ -455,7 +451,6 @@ class BibControllerWithAdminBibEditAnnecyPostWithVisibiliteZeroTest extends BibC 'gln' => '9876', 'visibilite' => '0', 'id_bib' => 2]); - } @@ -540,6 +535,128 @@ class BibControllerWithAdminBibEditAnnecyPostWithVisibiliteZeroAndSomeItemsTest +class BibControllerWithAdminBibEditAnnecyUploadPhotoTest extends BibControllerWithAdminBibTestCase { + public function setUp() { + unset($_FILES['photo']); + parent::setUp(); + $this->fixture('Class_Cosmogramme_Integration', + ['id' => 5, + 'id_bib' => 2]); + + + Class_UploadMover_HttpPost::setFileWriter($this->mock() + ->whenCalled('moveUploadedFile') + ->answers(true)); + + + Class_Bib::setDefaultImageFactory($this->mock() + ->whenCalled('thumbnailImage') + ->answers(true) + ->whenCalled('writeImage') + ->answers(true)); + } + + public function tearDown() { + unset($_FILES['photo']); + parent::tearDown(); + } + + + protected function postDispatchBib() { + $this->postDispatch('admin/bib/edit/id/2', + ['libelle' => 'Bonlieu', + 'responsable' => 'Ludivine', + 'id_bib' => 2]); + } + + + /** @test */ + public function savedImageShouldBeNamedTwo_PhotoDotPng() { + $_FILES['photo'] = ['size' => (250 * 1000), + 'name' => 'photo.png', + 'type' => 'image/png', + 'tmp_name' => 'toto.png', + 'error' => 0]; + + + $this->postDispatchBib(); + $this->assertEquals('2_photo.png', Class_Bib::find(2)->getFile()); + } + + + + /** @test */ + public function withCorrectImageShouldBeNamedTwo_PhotoDotPng() { + $_FILES['photo'] = ['size' => (250 * 1000), + 'name' => 'photo.png', + 'type' => 'image/png', + 'tmp_name' => 'toto.png', + 'error' => 0]; + + + $this->postDispatchBib(); + $this->assertEquals('2_photo.png', Class_Bib::find(2)->getFile()); + } + + + /** @test */ + public function withSizeGreaterThan250KioShouldDisplayErrorFileTooBig() { + $_FILES['photo'] = ['size' => (250 * 1000) + 1, + 'name' => 'photo.png', + 'type' => 'image/png', + 'tmp_name' => 'toto.png', + 'error' => 0]; + $this->postDispatchBib(); + $this->assertXPathContentContains('//ul[@class="errors"]//li', + 'La taille du fichier ne doit pas excéder 250ko'); + } + + + /** @test */ + public function withEmptyFileShouldDisplayErrorEmptyFile() { + $_FILES['photo'] = ['size' => 0, + 'name' => 'photo.png', + 'type' => 'image/png', + 'tmp_name' => 'toto.png', + 'error' => 0]; + + $this->postDispatchBib(); + $this->assertXPathContentContains('//ul[@class="errors"]//li', + 'Le fichier était vide'); + } + + + /** @test */ + public function withFileUploadErrorShouldDisplayFailure() { + $_FILES['photo'] = ['size' => 20, + 'name' => 'photo.png', + 'type' => 'image/png', + 'tmp_name' => 'toto.png', + 'error' => 3]; + + $this->postDispatchBib(); + $this->assertXPathContentContains('//ul[@class="errors"]//li', + 'Le fichier n\'a pu être téléchargé complètement'); + } + + + /** @test */ + public function updoadingTextFileShouldDisplayErrorWrongFileType() { + $_FILES['photo'] = ['size' => 200000, + 'name' => 'photo.txt', + 'type' => 'image/txt', + 'tmp_name' => 'toto.txt', + 'error' => 0]; + + $this->postDispatchBib(); + $this->assertXPathContentContains('//ul[@class="errors"]//li', + 'Le fichier n\'est pas de type jpg, gif, png, jpeg'); + } +} + + + + class BibControllerJSONTest extends BibControllerTestCase { /** @test */ function withBibThreeShouldRenderCranJSON() { @@ -853,6 +970,8 @@ class BibControllerLocalisationNewPostTest extends BibControllerTestCase { } + + class BibControllerLocalisatonDeleteTest extends BibControllerTestCase { public function setUp() { parent::setUp(); @@ -880,14 +999,16 @@ class BibControllerLocalisatonDeleteTest extends BibControllerTestCase { } + /** @test */ public function deleteShouldDeleteLocalisation() { $this->assertNull(Class_Localisation::find(9)); } - } + + class BibControllerPlanTest extends BibControllerTestCase { public function setUp() { parent::setUp(); @@ -913,8 +1034,6 @@ class BibControllerPlanTest extends BibControllerTestCase { 'libelle' => 'Mezzanine', 'description' => '', 'image' => 'mezzanine.png']); - - } /** @test */ @@ -929,10 +1048,11 @@ class BibControllerPlanTest extends BibControllerTestCase { $this->dispatch('admin/bib/plans/id_bib/3'); $this->assertXPath('//img[contains(@src,"plans/bib_3_plan_3.png")]',$this->_response->getBody()); } - } + + class BibControllerPlanMajTest extends BibControllerTestCase { public function setUp() { parent::setUp(); @@ -1358,4 +1478,4 @@ class BibControllerWithRemineAPIPostDispatchTest extends BibControllerWithRedmin public function libAnnecyRedmineAPIKeyShouldBe123456789() { $this->assertEquals('123456789', Class_Bib::find(2)->getRedmineApiKey()); } -} \ No newline at end of file +} diff --git a/tests/application/modules/opac/controllers/BibControllerTest.php b/tests/application/modules/opac/controllers/BibControllerTest.php index b3dfa1a1fe13f60f6d885d0b749023db1a1d4a84..bb4e4deecdf5a998e91171715162353ba09ed4e0 100644 --- a/tests/application/modules/opac/controllers/BibControllerTest.php +++ b/tests/application/modules/opac/controllers/BibControllerTest.php @@ -41,6 +41,7 @@ abstract class BibControllerWithZoneTestCase extends AbstractControllerTestCase 'mail' => 'jp@annecy.com', 'telephone' => '04 50 51 32 12', 'adresse' => '1 rue Jean Jaures', + 'photo' => '/userfiles/photobib/photobib4.jpg', 'visibilite' => Class_Bib::V_DATA]); $this->bib_nozone = $this->fixture('Class_Bib', ['id' => 22, @@ -321,7 +322,6 @@ abstract class BibControllerBibViewTestCase extends BibControllerWithZoneTestCas class BibControllerBibViewAnnecyTest extends BibControllerBibViewTestCase { - public function setUp() { parent::setUp(); @@ -336,11 +336,17 @@ class BibControllerBibViewAnnecyTest extends BibControllerBibViewTestCase { /** @test */ - function AdresseShouldBe1RueJeanJaures() { + function adresseShouldBe1RueJeanJaures() { $this->assertXPathContentContains('//dd', '1 rue Jean Jaures'); } + /** @test */ + public function photoBibShouldBeDisplayedWithClassBibviewImage() { + $this->assertXPath('//img[@class="bibview_image"][@src="'. BASE_URL .'/userfiles/photobib/photobib4.jpg"]'); + } + + /** @test */ function articleEcrivezDesTestsShouldBeVisible() { $this->assertXPathContentContains('//h2', 'Ecrivez des tests !'); diff --git a/tests/library/Class/AlbumTest.php b/tests/library/Class/AlbumTest.php index bbe111b7da7673baf5a378850434e023fd030df1..085dcafd33b95253ece99e82d255db94e62baaa6 100644 --- a/tests/library/Class/AlbumTest.php +++ b/tests/library/Class/AlbumTest.php @@ -256,7 +256,7 @@ abstract class AlbumHarlockFileUploadHandlerTestCase extends AlbumHarlockTestCas class AlbumHarlockReceivingFileTest extends AlbumHarlockFileUploadHandlerTestCase { /** @test */ public function withoutFileShouldReturnTrue() { - $_FILES['fichier']['size'] = 0; + $_FILES['fichier']['error'] = 4; $this->assertTrue($this->_album->receiveFile()); } @@ -264,6 +264,7 @@ class AlbumHarlockReceivingFileTest extends AlbumHarlockFileUploadHandlerTestCas /** @test */ public function withUploadErrorShouldReturnFalse() { $_FILES['fichier']['size'] = 1; + $_FILES['fichier']['error'] = 0; $this->_handler ->expects($this->once()) ->method('receive') @@ -283,6 +284,7 @@ class AlbumHarlockReceivingPdfTest extends AlbumHarlockFileUploadHandlerTestCase /** @test */ public function withoutFileShouldReturnTrue() { $_FILES['pdf']['size'] = 0; + $_FILES['pdf']['error'] = 4; $this->assertTrue($this->_album->receivePdf()); } @@ -290,10 +292,15 @@ class AlbumHarlockReceivingPdfTest extends AlbumHarlockFileUploadHandlerTestCase /** @test */ public function withUploadErrorShouldReturnFalse() { $_FILES['pdf']['size'] = 1; + $_FILES['pdf']['error'] = 0; $this->_handler ->expects($this->once()) ->method('receive') ->will($this->returnValue(false)); + $this->_handler + ->method('hasErrorCodeOnFile') + ->will($this->returnValue(false)); + $this->_handler ->expects($this->once()) diff --git a/tests/library/ZendAfi/View/Helper/Accueil/LibraryTest.php b/tests/library/ZendAfi/View/Helper/Accueil/LibraryTest.php index 5d9c9d05450cd58cefa34380629b5228c832634a..3c57753672564e1acefb83b708c1da9a70a77ef0 100644 --- a/tests/library/ZendAfi/View/Helper/Accueil/LibraryTest.php +++ b/tests/library/ZendAfi/View/Helper/Accueil/LibraryTest.php @@ -38,6 +38,7 @@ abstract class ZendAfi_View_Helper_Accueil_LibraryTestCase extends ViewHelperTes 'telephone' => '01 02 03 04 05', 'mail' => 'annecy@annecy.fr', 'ville' => 'Annecy', + 'photo' => 'annecy.jpg', 'cp' => '74000']); $this->cran = $this->fixture('Class_Bib', @@ -49,7 +50,8 @@ abstract class ZendAfi_View_Helper_Accueil_LibraryTestCase extends ViewHelperTes $this->seynod = $this->fixture('Class_Bib', ['id' => 3, - 'libelle' => 'Seynod']); + 'libelle' => 'Seynod', + 'photo' => '/userfiles/images/seynod.jpg',]); $this->meythet = $this->fixture('Class_Bib', ['id' => 4, @@ -60,7 +62,6 @@ abstract class ZendAfi_View_Helper_Accueil_LibraryTestCase extends ViewHelperTes protected function _generateLibrary($preferences) { - $params = ['type_module' => 'LIBRARY', 'division' => 2, 'preferences' => $preferences]; @@ -208,7 +209,8 @@ class ZendAfi_View_Helper_Accueil_LibraryFieldsDisplayTest extends ZendAfi_View_ $fields = implode([Class_Systeme_ModulesAccueil_Library::FIELD_MAIL, Class_Systeme_ModulesAccueil_Library::FIELD_ADDRESS, - Class_Systeme_ModulesAccueil_Library::FIELD_PHONE], ';'); + Class_Systeme_ModulesAccueil_Library::FIELD_PHONE, + Class_Systeme_ModulesAccueil_Library::FIELD_PICTURE], ';'); $this->_generateLibrary(['titre' => 'My library', 'libraries' => '1', @@ -233,6 +235,15 @@ class ZendAfi_View_Helper_Accueil_LibraryFieldsDisplayTest extends ZendAfi_View_ public function phoneShouldBeThirdField() { $this->assertXPathContentContains($this->html, '//div["fields"]//div[3]/p', '01 02 03 04 05'); } + + + + /** @test */ + public function annecyPictureSrcShouldContainsUserfilesPath() { + $this->assertXPath($this->html, + '//div[@class="field-picture"]/img[@class="bibview_image"][@src="' . BASE_URL . '/userfiles/photobib/annecy.jpg"]', + $this->html); + } }