diff --git a/VERSIONS b/VERSIONS index ac2ac22b01e8058718277db761661f981c9e8a40..04cf4d692e367f43e20a7b2c5eea6961bcd4d5dd 100644 --- a/VERSIONS +++ b/VERSIONS @@ -1,3 +1,14 @@ +06/04/2017 - v7.9.10 + + - ticket #57574 : Articles : correction de l'orthographe des jours de la semaine (tous les lundis, mardis ...) + + - ticket #58543 : Charte graphique : Ajout de la possibilité de personnaliser l'icone de localisation présent dans le bloc exemplaire + + - ticket #56365 : Newsletters : limite de longueur des titres passée à 255 octets + + - ticket #58096 : Avis sur les articles : Modification de la base de données qui dans certains cas empechait la création d'un avis + + 30/03/2017 - v7.9.9 - ticket #58461 : LeKiosk : Maintenance du lien SSO vers la nouvelle plateforme diff --git a/application/modules/admin/views/scripts/lieu/_lieu.phtml b/application/modules/admin/views/scripts/lieu/_lieu.phtml deleted file mode 100644 index 90e02c22a9eb1f9f9d3f3d98611c7e1654975287..0000000000000000000000000000000000000000 --- a/application/modules/admin/views/scripts/lieu/_lieu.phtml +++ /dev/null @@ -1,14 +0,0 @@ -<tr class="<?php echo $this->item_class ?>"> - <?php - echo sprintf("<td>%s</td>", $this->mapForLieu($this->lieu, array('size' => '100x100', 'zoom' => '12'))); - echo sprintf("<td>%s</td>", $this->lieu->getLibelle()); - echo sprintf("<td>%s %s</td>", - $this->tagAnchor(array('action' => 'edit', - 'id' => $this->lieu->getId()), - $this->boutonIco("type=edit")), - - $this->tagAnchor(array('action' => 'delete', - 'id' => $this->lieu->getId()), - $this->boutonIco("type=del"))); - ?> -</tr> \ No newline at end of file diff --git a/application/modules/admin/views/scripts/lieu/index.phtml b/application/modules/admin/views/scripts/lieu/index.phtml index f79267359f753170a0ccb59dd4b84a43c99ca1b1..e65b8ddafd073f8a15970acbd0663c1aab8e15b4 100644 --- a/application/modules/admin/views/scripts/lieu/index.phtml +++ b/application/modules/admin/views/scripts/lieu/index.phtml @@ -7,22 +7,19 @@ echo $this->button((new Class_Entity()) ->setUrl($this->url(['action' => 'update-coordinates'])) ->setImage($this->tagImg(Class_Admin_Skin::current()->renderIconUrlOn('buttons', 'generate')))); -?> -<table class="lieux"> - <thead> - <tr class="soustitre"> - <td>Carte</td> - <td>Libellé</td> - <td></td> - </tr> - </thead> - <tbody> -<?php - echo $this->partialCycle('lieu/_lieu.phtml', - 'lieu', - $this->lieux, - array('first', 'second')); + +echo $this->renderTable( + (new Class_TableDescription('lieux')) + ->addColumn($this->_('Carte'), + ['callback' => function($model) { + return $this->mapForLieu($model, + ['size' => '100x100', + 'zoom' => '12']); + }, + 'options' => ['data-sorter' => 'false']]) + ->addColumn($this->_('Libellé'), ['attribute' => 'libelle']) + ->addRowAction(['action' => 'edit', 'content' => $this->boutonIco("type=edit")]) + ->addRowAction(['action' => 'delete', 'content' => $this->boutonIco("type=del")]), + $this->lieux); ?> - </tbody> -</table> diff --git a/application/modules/admin/views/scripts/newsletter/index.phtml b/application/modules/admin/views/scripts/newsletter/index.phtml index 5b3543803b756d9c170b2cf1b52f159402a76680..84c8d933dc3dc54681f4cb475fe57e8fa153312d 100644 --- a/application/modules/admin/views/scripts/newsletter/index.phtml +++ b/application/modules/admin/views/scripts/newsletter/index.phtml @@ -2,16 +2,17 @@ echo $this->Button_New((new Class_Entity()) ->setText($this->_('Créer une lettre d\'information'))); -echo $this->tagModelTable($this->newsletters, - [$this->_('Titre'), $this->_('Dernière distribution')], - ['titre', 'progress'], - [function($model) - { - return $this->renderPluginsActions($model); - }], - 'newsletters', - null, - ['progress' => function($model) { return $this->tagProgressBarForNewsletter($model); }]); + +echo $this->renderTable( + (new Class_TableDescription('newsletters')) + ->addColumn($this->_('Titre'), ['attribute' => 'titre']) + ->addColumn($this->_('Dernière distribution'), + ['callback' => function($model) { + return $this->tagProgressBarForNewsletter($model); + }, + 'options' => ['class' => "dateFormat-ddmmyyyy sorter-shortDate"]]) + ->addRowAction(function($model) { return $this->renderPluginsActions($model); }), + $this->newsletters); if (isset($this->subview)) echo $this->tag('div', $this->subview, ['class' => 'subview']); diff --git a/cosmogramme/sql/patch/patch_322.php b/cosmogramme/sql/patch/patch_322.php new file mode 100644 index 0000000000000000000000000000000000000000..1feedcb4820cdd107353b41c3fedd96629b75ee0 --- /dev/null +++ b/cosmogramme/sql/patch/patch_322.php @@ -0,0 +1,9 @@ +<?php +$adapter = Zend_Db_Table::getDefaultAdapter(); +try { + $adapter->query('select flags from cms_avis limit 1'); +} catch (Exception $e) { + $adapter->query('ALTER TABLE cms_avis ADD COLUMN flags tinyint default 0'); + $adapter->query('ALTER TABLE cms_avis ADD INDEX (flags)'); +} +?> diff --git a/cosmogramme/sql/patch/patch_323.php b/cosmogramme/sql/patch/patch_323.php new file mode 100644 index 0000000000000000000000000000000000000000..537b349832738e5695ed0e24f4a0c676736da622 --- /dev/null +++ b/cosmogramme/sql/patch/patch_323.php @@ -0,0 +1,6 @@ +<?php +try { + Zend_Db_Table_Abstract::getDefaultAdapter() + ->query('alter table newsletters modify column titre varchar(255) not null'); +} catch(Exception $e) {} +?> \ No newline at end of file diff --git a/library/Class/Profil.php b/library/Class/Profil.php index 05a50f5e37b3a9c2a73d0b70b497222e64530b46..4d33dfbd5f502c2beea48c2e6f1bc8ab9b2073f8 100644 --- a/library/Class/Profil.php +++ b/library/Class/Profil.php @@ -518,6 +518,13 @@ class Class_Profil extends Storm_Model_Abstract { } + /** @category testing */ + public function setDefaultSkin($skin) { + $this->_skin = $skin; + return $this; + } + + protected function _getSkin() { if (null === $this->_skin) $this->_skin = Class_Profil_Skin::newFor($this); diff --git a/library/Class/TableDescription.php b/library/Class/TableDescription.php new file mode 100644 index 0000000000000000000000000000000000000000..30f105e58c143ddced0167d7a4d9bf22f6fdb360 --- /dev/null +++ b/library/Class/TableDescription.php @@ -0,0 +1,322 @@ +<?php +/** + * Copyright (c) 2012-2017, 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 Class_TableDescription { + protected + $_columns, + $_id; + + public function __construct($id) { + $this->_id = $id; + $this->_columns = new Class_TableDescription_Columns(); + } + + + public function getId() { + return $this->_id; + } + + + public function columnsCollect($callback) { + return $this->_columns->collect($callback); + } + + + public function addColumn($label, $description) { + $description = array_merge(['attribute' => '', + 'callback' => null, + 'options' => ''], + $description); + $this + ->_columns + ->add($this->newColumn($label, $description) + ->setOptions($description['options'])); + + return $this; + } + + + public function newColumn($label, $description) { + return $description['callback'] + ? new Class_TableDescription_ColumnForCallback($label, + $description['attribute'], + $description['callback']) + : new Class_TableDescription_ColumnForAttribute($label, + $description['attribute']); + } + + + public function getActionColumn() { + if (!isset($this->_actions)) { + $this->_actions = (new Class_TableDescription_ColumnForActions()) + ->setOptions(['data-sorter' => 'false', + 'class' => 'actions', + 'style' => 'min-width: 80px']); + $this->_columns->add($this->_actions); + } + + return $this->_actions; + } + + + public function addRowAction($description) { + $this->getActionColumn() + ->add(Class_TableDescription_ActionAbstract::forDescription($description)); + return $this; + } + + public function numberOfColumns() { + return $this->_columns->count(); + } +} + + + +class Class_TableDescription_Columns { + protected $_columns; + + public function __construct() { + $this->_columns = new Storm_Collection(); + } + + + public function collect($callback) { + return $this->_columns->collect($callback); + } + + + public function count() { + return $this->_columns->count(); + } + + + /** @return Class_TableDescription_ColumnAbstract subclass */ + public function add($column) { + $this->_columns->append($column); + return $column; + } + + + public function acceptVisitor($visitor) { + $this->_columns->eachDo(function($column) use($visitor) + { + $visitor->visitColumn($column); + }); + } +} + + + +abstract class Class_TableDescription_ColumnAbstract { + protected + $_label, + $_options = []; + + + public function __construct($label) { + $this->_label = $label; + } + + + public function getLabel() { + return $this->_label; + } + + + public function setOptions($options) { + $this->_options = $options; + return $this; + } + + + public function getOptions() { + return $this->_options; + } + + + abstract public function renderModelOn($model, $canvas); +} + + + + +class Class_TableDescription_ColumnForCallback extends Class_TableDescription_ColumnAbstract { + protected + $_callback, + $_attribute; + + public function __construct($label, $attribute, $callback) { + parent::__construct($label); + $this->_attribute = $attribute; + $this->_callback = $callback; + } + + + public function renderModelOn($model, $canvas) { + return $canvas->renderContent(call_user_func($this->_callback, + $model, + $this->_attribute)); + } +} + + + +class Class_TableDescription_ColumnForAttribute extends Class_TableDescription_ColumnAbstract { + protected $_attribute; + + public function __construct($label, $attribute) { + parent::__construct($label); + $this->_attribute = $attribute; + } + + + public function renderModelOn($model, $canvas) { + return $canvas->renderContent($model->callGetterByAttributeName($this->_attribute)); + } +} + + + + +class Class_TableDescription_ColumnForActions extends Class_TableDescription_ColumnAbstract { + use Trait_Translator; + + protected $_actions; + + public function __construct() { + parent::__construct($this->_('Actions')); + $this->_actions = new Storm_Collection(); + } + + + /** @return Class_TableDescription_ActionAbstract */ + public function add($action) { + $this->_actions->append($action); + return $action; + } + + + public function renderModelOn($model, $canvas) { + $this->_actions->eachDo(function($action) use ($model, $canvas) + { + return $action->renderModelOn($model, $canvas); + }); + } +} + + + + +abstract class Class_TableDescription_ActionAbstract { + public static function forDescription($description) { + if (is_a($description, 'Closure')) + return new Class_TableDescription_ActionCallback($description); + + $classname = is_a($description['content'], 'Closure') + ? 'Class_TableDescription_ActionWithContentCallback' + : 'Class_TableDescription_Action'; + + return new $classname($description['action'], $description['content']); + } + + abstract public function renderModelOn($model, $canvas); +} + + + + +class Class_TableDescription_ActionCallback extends Class_TableDescription_ActionAbstract { + protected $_callback; + + public function __construct($callback) { + $this->_callback = $callback; + } + + + public function renderModelOn($model, $canvas) { + return $canvas->renderContent(call_user_func_array($this->_callback, [$model])); + } +} + + + + +class Class_TableDescription_ActionWithContentCallback extends Class_TableDescription_ActionAbstract { + protected + $_content_callback, + $_action; + + public function __construct($action, $content_callback) { + $this->_content_callback = $content_callback; + $this->_action = $action; + } + + + public function renderModelOn($model, $canvas) { + return $canvas->tag('a', + call_user_func($this->_content_callback, $model), + $this->_anchorAttributes($model, $canvas)); + } + + + protected function _anchorAttributes($model, $canvas) { + $url = Class_Url::assemble(['action' => $this->_action, + 'id' => $model->getId()], + null, + false); + + $attribs = ['href' => $url, 'rel' => $this->_action]; + + if ($this->_isUrlMatchesCurrent($url)) + $attribs['class'] = 'selected'; + + return $attribs; + } + + + protected function _isUrlMatchesCurrent($url) { + return + isset($_SERVER['REQUEST_URI']) + && + (false !== strpos($_SERVER['REQUEST_URI'], $url)); + } +} + + + + +class Class_TableDescription_Action extends Class_TableDescription_ActionWithContentCallback { + protected + $_content; + + public function __construct($action, $content) { + $this->_content = $content; + parent::__construct($action, [$this, 'getContent']); + } + + + public function getContent() { + return $this->_content; + } +} + +?> \ No newline at end of file diff --git a/library/Class/TableDescription/Models.php b/library/Class/TableDescription/Models.php new file mode 100644 index 0000000000000000000000000000000000000000..323f1675e5e4292d1cee77c990a379af6c638911 --- /dev/null +++ b/library/Class/TableDescription/Models.php @@ -0,0 +1,108 @@ +<?php +/** + * Copyright (c) 2012-2017, 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 Class_TableDescription_Models { + protected + $_models, + $_groups; + + public function __construct($models) { + $this->_models = new Storm_Collection($models); + $this->groupBy(null); + } + + + public function groupBy($group_by) { + if (!$group_by) { + $this->_groups = [new Class_TableDescription_ModelGroup($this->_models)]; + return $this; + } + + $this->_groups = []; + $this ->_models->eachDo(function($model) use ($group_by) + { + $this->_placeModelInGroups($model, $group_by); + }); + return $this; + } + + + public function renderOn($canvas) { + array_map(function($group) use ($canvas) + { + $group->renderOn($canvas); + }, + $this->_groups); + } + + + protected function _placeModelInGroups($model, $group_by) { + $group = $model->callGetterByAttributeName($group_by); + if (!array_key_exists($group, $this->_groups)) + $this->_groups[$group] = new Class_TableDescription_ModelGroup_Indexed($group); + $this->_groups[$group]->add($model) ; + } +} + + + + +class Class_TableDescription_ModelGroup { + protected $_models; + + public function __construct($models = null) { + $this->_models = $models + ? $models + : new Storm_Collection(); + } + + + public function add($model) { + $this->_models->append($model); + } + + + public function renderOn($canvas) { + $canvas->renderModels($this->_models->getArrayCopy()); + } +} + + + + +class Class_TableDescription_ModelGroup_Indexed extends Class_TableDescription_ModelGroup { + protected + $_key; + + public function __construct($key) { + parent::__construct(); + $this->_key = $key; + } + + + public function renderOn($canvas) { + $canvas->renderGroupTitle($this->_key); + parent::renderOn($canvas); + } +} + +?> \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/Notice/ExemplairesTable.php b/library/ZendAfi/View/Helper/Notice/ExemplairesTable.php index e79914121d441db56895641c16d6c176eab13d81..03f9281757931c18e186b901c150345309e845e0 100644 --- a/library/ZendAfi/View/Helper/Notice/ExemplairesTable.php +++ b/library/ZendAfi/View/Helper/Notice/ExemplairesTable.php @@ -319,13 +319,17 @@ class ZendAfi_View_Helper_Notice_Exemplaires_Localisation extends ZendAfi_View_H return $this->_('Situer'); } + public function renderContent($exemplaire) { - $html='<td class="localisation" style="text-align:center">'; + return $this->_tag('td', $this->_getLocalisationLink($exemplaire), + ['class' => 'localisation', + 'style' => 'text-align:center']); + } - $id = $exemplaire->getIdBib(); - if ($annexe = Class_CodifAnnexe::findFirstBy(['code' => $exemplaire->getAnnexe()])) - $id = $annexe->getIdBib(); + protected function _getLocalisationLink($exemplaire) { + if (0 == $this->getBib($exemplaire)->numberOfLocalisations()) + return ' '; $url = CLass_Url::absolute(['module' => 'opac', 'controller' => 'noticeajax', @@ -334,18 +338,17 @@ class ZendAfi_View_Helper_Notice_Exemplaires_Localisation extends ZendAfi_View_H $onclick = 'localisationExemplaire(this, \'' . $url . '\')'; - if ($this->getBib($exemplaire)->numberOfLocalisations()>0) - $html.= sprintf('<img src="%s" border="0" title="%s" style="cursor:pointer" onclick="%s" alt="%s" />', - URL_ADMIN_IMG.'picto/localisation.png', - $this->_('Situer cet exemplaire dans la bibliothèque'), - $onclick, - $this->_('Situer en exemplaire')); - else - $html.=' '; - $html.='</td>'; - return $html; + return $this->view + ->tagImg($this->_getPictoUrl(), + ['title' => $this->_('Situer cet exemplaire dans la bibliothèque'), + 'style' => 'border-style:none;cursor:pointer', + 'onclick' => $onclick]); } + + protected function _getPictoUrl() { + return Class_Profil::getCurrentProfil()->getUrlImage('localisation.png'); + } } @@ -355,20 +358,34 @@ class ZendAfi_View_Helper_Notice_Exemplaires_Plan extends ZendAfi_View_Helper_No return $this->_('Plan'); } + public function renderContent($exemplaire) { - $html='<td class="gmap" style="text-align:center;">'; + return $this->_tag('td', $this->_getMapLink($exemplaire), + ['class' => 'gmap', + 'style' => 'text-align:center']); + } - if($this->getBib($exemplaire)->getGoogleMap() > "") - $html .= sprintf('<a href="%s"><img src="%s" border="0" alt="%s" title="%s" /></a>', - BASE_URL.'/bib/mapview?id_bib='.$exemplaire->getIdBib() .'&retour=notice', - URL_ADMIN_IMG.'picto/map.gif', - $this->_('Afficher la carte'), - $this->_('Afficher la carte')); - else $html.=' '; - $html.='</td>'; - return $html; + + protected function _getMapLink($exemplaire) { + if (!$this->getBib($exemplaire)->getGoogleMap()) + return ' '; + + return $this->_tag('a', $this->_getPicto(), + ['href' => BASE_URL.'/bib/mapview?id_bib='.$exemplaire->getIdBib() .'&retour=notice']); + } + + + protected function _getPicto() { + return $this->view->tagImg($this->_getPictoUrl(), + ['title' => $this->_('Afficher la carte'), + 'alt' => $this->_('Afficher la carte'), + 'style' => 'border-style:none;']); } + + protected function _getPictoUrl() { + return Class_Profil::getCurrentProfil()->getUrlImage('map.gif'); + } } @@ -378,10 +395,10 @@ class ZendAfi_View_Helper_Notice_Exemplaires_Resa extends ZendAfi_View_Helper_No return $this->_('Réserver'); } + public function renderContent($exemplaire) { return $this->view->Notice_ReservationLink($this->getBib($exemplaire), $exemplaire, ''); } - } @@ -390,10 +407,10 @@ class ZendAfi_View_Helper_Notice_Exemplaires_Consultation extends ZendAfi_View_H return $this->_('Consultation sur place'); } + public function renderContent($exemplaire) { return $this->view->Notice_ConsultationLink($this->getBib($exemplaire), $exemplaire, ''); } - } @@ -403,22 +420,33 @@ class ZendAfi_View_Helper_Notice_Exemplaires_Oeuvre extends ZendAfi_View_Helper_ return $this->_('Voir'); } + public function renderContent($exemplaire) { + return $this->_tag('td', $this->_getWorkLink($exemplaire), + ['class' => 'oeuvre', + 'style' => 'text-align:center']); + } + + + protected function _getWorkLink($exemplaire) { + return $this->_tag('a', $this->_getPicto(), + ['href' => $this->view->url(['controller' => 'recherche', + 'action' => 'viewnotice', + 'id' => $exemplaire->getIdNotice()])]); + } - $html='<td class="oeuvre" style="text-align:center;">'; - $html.= sprintf('<a href="%s"> <img src="%s" border="0" alt="%s" title="%s" /></a>', - $this->view->url(['controller' => 'recherche', - 'action' => 'viewnotice', - 'id' => $exemplaire->getIdNotice()]), - URL_IMG.'bouton/loupe.gif', - $this->_('Afficher la notice'), - $this->_('Afficher la notice') - ); - $html.='</td>'; - return $html; + protected function _getPicto() { + return $this->view->tagImg($this->_getPictoUrl(), + ['title' => $this->_('Afficher la notice'), + 'alt' => $this->_('Afficher la notice'), + 'style' => 'border-style:none;']); } + + protected function _getPictoUrl() { + return Class_Profil::getCurrentProfil()->getUrlImage('bouton/loupe.gif'); + } } diff --git a/library/ZendAfi/View/Helper/RenderTable.php b/library/ZendAfi/View/Helper/RenderTable.php new file mode 100644 index 0000000000000000000000000000000000000000..92f431dacf65e6a3bc33afbb6f6cbfb623364b88 --- /dev/null +++ b/library/ZendAfi/View/Helper/RenderTable.php @@ -0,0 +1,194 @@ +<?php +/** + * Copyright (c) 2012-2017, 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_RenderTable extends ZendAfi_View_Helper_BaseHelper { + /** + * @param description Class_TableDescription + * @param grouped_models Class_TableDescription_Models or Array + * @param options Array + */ + public function renderTable($description, $grouped_models, $options = []) { + $grouped_models = is_array($grouped_models) + ? new Class_TableDescription_Models($grouped_models) + : $grouped_models; + + $options = array_merge(['pager' => false], $options); + Class_ScriptLoader::getInstance()->loadTableSorter($options['pager']); + + return + $this->_tag('table', + $this->_head($description) + .$this->_body($description, $grouped_models), + ['id' => $description->getId(), + 'class' => 'models tablesorter']) + . $this->_renderPager($options); + } + + + protected function _head($description) { + return $this->view->renderTable_Header($description); + } + + + protected function _body($description, $grouped_models) { + return $this->view->renderTable_Body($description, $grouped_models); + } + + + protected function _renderPager($options) { + if (!$options['pager']) + return ''; + + $first = $this->_tag('span', '|<<' , ['class' => 'first', + 'style' => 'cursor:pointer']); + + $previous = $this->_tag('span', '<' , ['class' => 'first', + 'style' => 'cursor:pointer']); + + $page_display = $this->_tag('input', '', ['class' => 'pagedisplay']); + + $next = $this->_tag('span', '>' , ['class' => 'next', + 'style' => 'cursor:pointer']); + + $last = $this->_tag('span', '>>|' , ['class' => 'last', + 'style' => 'cursor:pointer']); + + $select = $this->view->formSelect('pagesize', + '', + ['class' => 'pagesize'], + ['10' => 10, + '20' => 20, + '30' => 30]); + $html = $first . + $previous . + $page_display. + $next . + $last . + $select; + + $form = $this->_tag('form', $html); + + return $this->_tag('div', $form, ['class' => 'pager model_table_pager']); + } +} + + + + +class ZendAfi_View_Helper_RenderTable_Header extends ZendAfi_View_Helper_BaseHelper { + public function renderTable_Header($description) { + return $this->_tag('thead', + $this->_tag('tr', + $this->_renderColumns($description))); + } + + + protected function _renderColumns($description) { + return implode('', + $description->columnsCollect([$this, '_renderColumn']) + ->getArrayCopy()); + } + + + public function _renderColumn($column) { + return $this->_tag('th', + $column->getLabel(), + $column->getOptions() ? $column->getOptions() : null); + } +} + + + + +class ZendAfi_View_Helper_RenderTable_Body extends ZendAfi_View_Helper_BaseHelper { + protected + $_description, + $_html; + + public function renderTable_Body($description, $grouped_models) { + $this->_description = $description; + + $this->_html = ''; + $grouped_models->renderOn($this); + return $this->_tag('tbody', + $this->_html); + + } + + + public function renderModels($models) { + $this->_html .= implode('', + array_map([$this, '_renderModelRaw'], + $models)); + } + + + public function renderGroupTitle($title) { + $this->_html .= $this->_tag('tr', + $this->_tag('td', + $this->view->escape($title), + ['style' => 'background-color:#888;color:white;font-size:120%;padding:2px 10px;font-weight:bold;', + 'colspan' => $this->_description->numberOfColumns()])); + } + + + protected function _renderModelRaw($model) { + return $this->_tag('tr', + implode('', + $this->_renderModelColumns($model) + ->getArrayCopy())); + } + + protected function _renderModelColumns($model) { + return $this + ->_description + ->columnsCollect(function($column) use ($model) + { + return $this->view->renderTable_Cell($column, $model); + }); + } +} + + + +class ZendAfi_View_Helper_RenderTable_Cell extends ZendAfi_View_Helper_BaseHelper { + protected $_html; + + public function renderTable_Cell($column, $model) { + $this->_html = ''; + $column->renderModelOn($model, $this); + return $this->_tag('td', + $this->_html); + } + + + public function renderContent($html) { + $this->_html .= $html; + } + + + public function tag($name, $content=null, $attribs=[]) { + $this->renderContent($this->_tag($name, $content, $attribs)); + } +} + +?> \ No newline at end of file diff --git a/library/ZendAfi/View/Helper/TagArticleEvent.php b/library/ZendAfi/View/Helper/TagArticleEvent.php index 3cc5645c6f2d44f6a2d45902f68bde05cd73d77a..ec145a0aaef186ecb45e1a4bce62ed59a0a84f16 100644 --- a/library/ZendAfi/View/Helper/TagArticleEvent.php +++ b/library/ZendAfi/View/Helper/TagArticleEvent.php @@ -94,9 +94,9 @@ class ZendAfi_View_Helper_TagArticleEvent extends Zend_View_Helper_HtmlElement { $textual_days = ''; foreach($days as $day) - $textual_days.= $this->numericDayToTextual($day) . ', '; + $textual_days.= $this->numericDayToTextual($day) . $this->view->_('s, '); - return substr($textual_days, 0, -2) . $this->view->_('s et ') . $last; + return substr($textual_days, 0, -2) . $this->view->_(' et ') . $last; } diff --git a/library/ZendAfi/View/Helper/TagModelTable.php b/library/ZendAfi/View/Helper/TagModelTable.php index 5402ad9c0dbdc523a6768d039d230ca8a95553e4..34bc2515e9ca5d53b2c8baf638c72eb0ff270a01 100644 --- a/library/ZendAfi/View/Helper/TagModelTable.php +++ b/library/ZendAfi/View/Helper/TagModelTable.php @@ -19,12 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ class ZendAfi_View_Helper_TagModelTable extends ZendAfi_View_Helper_BaseHelper { - /** @var boolean */ - protected $_hasActions = false; - /** @var int */ - protected $_cols_count = 0; - - /** Exemple: @@ -40,176 +34,27 @@ class ZendAfi_View_Helper_TagModelTable extends ZendAfi_View_Helper_BaseHelper { 'relations'); */ public function tagModelTable($models, $cols, $attribs, $actions, $id, $group_by = null, $callbacks = [], $pager = false) { - Class_ScriptLoader::getInstance()->loadTableSorter($pager); - - $this->_hasActions = 0 < count($actions); - $this->_cols_count = count($attribs) + ($this->_hasActions ? 1 : 0); - - $html = $this->_tag('table', - $this->head($cols) - .$this->tbody($models, $attribs, $actions, $group_by, $callbacks), - ['id' => $id, - 'class' => 'models tablesorter']); - - return $html . $this->_getPager($pager); - } - - - protected function _getPager($pager) { - if(!$pager) - return ''; - - $first = $this->_tag('span', '|<<' , ['class' => 'first', - 'style' => 'cursor:pointer']); - - $previous = $this->_tag('span', '<' , ['class' => 'first', - 'style' => 'cursor:pointer']); - - $page_display = $this->_tag('input', '', ['class' => 'pagedisplay']); - - $next = $this->_tag('span', '>' , ['class' => 'next', - 'style' => 'cursor:pointer']); - - $last = $this->_tag('span', '>>|' , ['class' => 'last', - 'style' => 'cursor:pointer']); - - $select = $this->view->formSelect('pagesize', - '', - ['class' => 'pagesize'], - ['10' => 10, - '20' => 20, - '30' => 30]); - $html = $first . - $previous . - $page_display. - $next . - $last . - $select; - - $form = $this->_tag('form', $html); - - return $this->_tag('div', $form, ['class' => 'pager model_table_pager']); - } - - - public function head($cols) { - if (!$cols) - return ''; - - $cols_html = ''; - foreach ($cols as $col) - $cols_html .= $this->_tag('th', $col); - - $actions = $this->_hasActions ? $this->_tag('th', $this->view->_('Actions'), - ['class' => 'actions', - 'data-sorter' => 'false', - 'style' => 'min-width: 80px;']) : ''; - - return $this->_tag('thead', - $this->_tag('tr', $cols_html . $actions)); - } - - - public function tbody($models, $attribs, $actions, $group_by, $callbacks) { - $rows = ''; - - $groups = []; - if (null != $group_by) { - foreach ($models as $model) { - $group = $model->callGetterByAttributeName($group_by); - if (!array_key_exists($group, $groups)) - $groups[$group] = []; - $groups[$group][] = $model; - } - } else { - $groups['no_group'] = $models; + $description = new Class_TableDescription($id); + foreach($cols as $i => $col) { + $attribute = $attribs[$i]; + $args = [ + 'attribute' => $attribute, + 'callback' => array_key_exists($attribute, $callbacks) ? $callbacks[$attribute] : null + ]; + + $description->addColumn($col, array_filter($args)); } - return $this->_tag('tbody', - $this->renderGroupsAsTableRows($groups, $attribs, $actions, $callbacks)); - } + if (!is_array($actions)) + $actions = []; - - public function renderGroupsAsTableRows($groups, $attribs, $actions, $callbacks) { - $rows = ''; - - foreach ($groups as $name => $groupModels) { - if ('no_group' != $name && '' != $name) - $rows .= $this->_tag('tr', - $this->_tag('td', - $this->view->escape($name), - ['style' => 'background-color:#888;color:white;font-size:120%;padding:2px 10px;font-weight:bold;', - 'colspan' => $this->_cols_count])); - - $rows .= $this->renderModelsAsTableRows($groupModels, $attribs, $actions, $callbacks); - } - - return $rows; - } - - - public function renderModelsAsTableRows($groupModels, $attribs, $actions, $callbacks) { - $rows = ''; - foreach ($groupModels as $model) - $rows .= $this->renderModelAsTableRow($model, $attribs, $actions, $callbacks); - return $rows; - } - - - public function renderModelAsTableRow($model, $attribs, $actions, $callbacks) { - $cols = ''; - - $default_callback = function ($model, $attrib) { - return $this->view->escape($model->callGetterByAttributeName($attrib)); - }; - - foreach ($attribs as $attrib) { - $callback = (array_key_exists($attrib, $callbacks)) ? $callbacks[$attrib] : $default_callback; - $cols .= $this->_tag('td', $callback($model, $attrib)); + foreach($actions as $action) { + $description->addRowAction($action); } - $actions = ($this->_hasActions) ? - $this->_tag('td', $this->renderModelActions($model, $actions)) : ''; - - return $this->_tag('tr', $cols . $actions); - } - - - /** - * @param Storm_Model_Abstract $model - * @param array of arrays of string / Closure $actions - * @return string - */ - public function renderModelActions($model, $actions) { - $html = ''; - foreach ($actions as $action) - $html .= $this->renderModelAction($model, $action); - - return $html; - } - - - /** - * @param Storm_Model_Abstract $model - * @param array of strings/closure or closure - * @return string - */ - public function renderModelAction($model, $action) { - if (is_a($action, 'Closure')) - return $action($model); - - $content = $action['content']; - $url = $this->view->url(['action' => $action['action'], 'id' => $model->getId()]); - $attribs = ['href' => $url, 'rel' => $action['action']]; - - if (isset($_SERVER['REQUEST_URI']) - && false !== strpos($_SERVER['REQUEST_URI'], $url)) - $attribs['class'] = 'selected'; - - return $this->view - ->tag('a', - is_a($content, 'Closure') ? $content($model) : $content, - $attribs); + return $this->view->renderTable($description, + (new Class_TableDescription_Models($models))->groupBy($group_by), + ['pager' => $pager]); } } ?> diff --git a/library/ZendAfi/View/Helper/TagProgressBarForNewsletter.php b/library/ZendAfi/View/Helper/TagProgressBarForNewsletter.php index 61aaf0fa303ba9b6c7ec14ebb9d432ef9b9232ae..23fa1a93ff2f131e35f1012a27682ae3a6556939 100644 --- a/library/ZendAfi/View/Helper/TagProgressBarForNewsletter.php +++ b/library/ZendAfi/View/Helper/TagProgressBarForNewsletter.php @@ -32,7 +32,8 @@ class ZendAfi_View_Helper_TagProgressBarForNewsletter extends ZendAfi_View_Helpe '$("#progress_bar_newsletter_'.$newsletter->getId().' span").html(data.status);'. 'if(!data.total) {'. '$("#progress_bar_newsletter_'.$newsletter->getId().'").html(data.status);'. - 'initializePopups();'. + 'initializePopups();'. + '$(".tablesorter").trigger("update");'. 'return true;'. '}'. '$("#progress_bar_newsletter_'.$newsletter->getId().'").progressbar({value: data.done, max: data.total});'. diff --git a/library/startup.php b/library/startup.php index 0402716d1928250a71cc57bd0d08c05f1a7385a3..6f29cfc6a9db540284e7f58fcb1beac249d54c0c 100644 --- a/library/startup.php +++ b/library/startup.php @@ -83,7 +83,7 @@ class Bokeh_Engine { function setupConstants() { defineConstant('BOKEH_MAJOR_VERSION','7.9'); - defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.9'); + defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.10'); defineConstant('BOKEH_REMOTE_FILES', 'http://git.afi-sa.fr/afi/opacce/'); diff --git a/public/opac/images/localisation.png b/public/opac/images/localisation.png new file mode 100644 index 0000000000000000000000000000000000000000..f19475ccd8e6313a7763023af903c875dc93ee8b Binary files /dev/null and b/public/opac/images/localisation.png differ diff --git a/public/opac/images/map.gif b/public/opac/images/map.gif new file mode 100644 index 0000000000000000000000000000000000000000..f7f09a2a09e31d80c4feb2f47de408d89bd828be Binary files /dev/null and b/public/opac/images/map.gif differ diff --git a/tests/application/modules/admin/controllers/LieuControllerTest.php b/tests/application/modules/admin/controllers/LieuControllerTest.php index 6991c1767fd98bb53f8640800fd45df2c5f144b6..15eb8502f273e35d9b75701ed4283c1509a26740 100644 --- a/tests/application/modules/admin/controllers/LieuControllerTest.php +++ b/tests/application/modules/admin/controllers/LieuControllerTest.php @@ -57,7 +57,7 @@ abstract class LieuControllerTestCase extends AbstractControllerTestCase { class LieuControllerListTest extends LieuControllerTestCase { public function setUp() { parent::setUp(); - $this->dispatch('/admin/lieu'); + $this->dispatch('/admin/lieu', true); } diff --git a/tests/application/modules/admin/controllers/NewsletterControllerTest.php b/tests/application/modules/admin/controllers/NewsletterControllerTest.php index 74fe8a9ba4c082c6c9f86c6197ef7d24e7967fa9..01a09fd7340e04cc8a73e4352bb3b857e86cba17 100644 --- a/tests/application/modules/admin/controllers/NewsletterControllerTest.php +++ b/tests/application/modules/admin/controllers/NewsletterControllerTest.php @@ -114,6 +114,12 @@ class Admin_NewsletterControllerIndexActionTest extends Admin_NewsletterControll } + /** @test */ + public function publicationDateColumnShouldHaveClassDateFormatDDMMYYYYForTableSorter() { + $this->assertXPath('//table//tr//th[2][contains(@class, "dateFormat-ddmmyyyy")]'); + } + + /** @test */ public function configLinkShouldBePresent() { $this->assertXPath('//h1//a[contains(@href, "newsletter/config")]'); diff --git a/tests/application/modules/admin/controllers/TypeDocsControllerTest.php b/tests/application/modules/admin/controllers/TypeDocsControllerTest.php index 74654327cc7ce755f40b4f8338147eea443a0111..d51cfe85c4c1474ac2215048dcecf78fecd4ff44 100644 --- a/tests/application/modules/admin/controllers/TypeDocsControllerTest.php +++ b/tests/application/modules/admin/controllers/TypeDocsControllerTest.php @@ -62,7 +62,7 @@ class TypeDocsControllerIndexTest extends AbstractTypeDocsControllerTestCase { /** @test */ public function actionColumnShouldHaveSorterFalse() { - $this->assertXPath('//thead//th[3][@class="actions"][@data-sorter="false"]'); + $this->assertXPath('//thead//th[3][@class="actions"][@data-sorter="false"]', $this->_response->getBody()); } diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerItemsTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerItemsTest.php index 686b630c532cda4aedd7319657de9cc5ed384a03..6a24a0c5f2732867af4c89ee660870f0de915dc5 100644 --- a/tests/application/modules/opac/controllers/NoticeAjaxControllerItemsTest.php +++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerItemsTest.php @@ -31,6 +31,12 @@ abstract class NoticeAjaxControllerItemsTestCase extends AbstractControllerTestC 'comm_sigb' => Class_IntBib::COM_VSMART ]); + $this->fixture('Class_Bib', + ['id' => 3, + 'google_map' => 1, + 'localisations' => [$this->fixture('Class_Localisation', + ['id' => 43])]]); + $itemA = $this->fixture('Class_Exemplaire', ['id' => 12, @@ -230,4 +236,50 @@ class NoticeAjaxControllerItemsFiltredByProfilAnnexTest extends NoticeAjaxContro public function itemBShouldNotBePresent() { $this->assertNotXPathContentContains('//td[@class="cote"]', 'B'); } +} + + + + +class NoticeAjaxControllerItemsCustomIconsTest + extends NoticeAjaxControllerItemsTestCase { + + protected function _prepareFixtures() { + $profil = Class_Profil::getCurrentProfil(); + $config = $profil->getCfgNoticeAsArray(); + $config['exemplaires']['grouper'] = '1'; + $config['exemplaires']['order_by'] = '9'; + $config['exemplaires']['order_direction'] = 'DESC'; + $profil->setCfgNotice($config); + + $profil->setDefaultSkin($this->mock() + ->whenCalled('getPath')->answers('/skins/customized') + ->whenCalled('getTemplatesPath')->answers('/skins/customized/html') + ->whenCalled('getImageUrl') + ->willDo(function($image) + { + return '/skins/customized/images/' . $image; + }) + ); + } + + + public function tearDown() { + Class_Profil::getCurrentProfil()->setDefaultSkin(null); + parent::tearDown(); + } + + + /** @test */ + public function locationIconShouldBeCustom() { + $this->assertXPath('//img[contains(@src, "/customized/images/localisation.png")]', + $this->_response->getBody()); + } + + + /** @test */ + public function mapIconShouldBeCustom() { + $this->assertXPath('//img[contains(@src, "/customized/images/map.gif")]', + $this->_response->getBody()); + } } \ No newline at end of file diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php index 86ea24b584c9dc3e8e0c19eab0dbfef1843f701d..4e18f6d68391354005608a0cc20f9d04e722cb57 100644 --- a/tests/db/UpgradeDBTest.php +++ b/tests/db/UpgradeDBTest.php @@ -179,7 +179,9 @@ abstract class UpgradeDBTestCase extends PHPUnit_Framework_TestCase { protected function assertField($table, $column, $expected, $field, $message = '') { try { + $fields = []; foreach($this->query(sprintf('show fields from `%s` where field=\'%s\'', $table, $column))->fetchAll() as $row) { + $fields[] = $row; if ($expected == $row[$field]) return true; } @@ -189,8 +191,8 @@ abstract class UpgradeDBTestCase extends PHPUnit_Framework_TestCase { $message = $message ? $message - : sprintf('Failed asserting that TABLE %s contains COLUMN %s with field %s = %s', - $table, $column, $field, $expected); + : sprintf('Failed asserting that TABLE %s contains COLUMN %s with field %s = %s, %s', + $table, $column, $field, $expected, json_encode($fields)); $this->fail($message); } @@ -1322,7 +1324,42 @@ class UpgradeDB_320_Test extends UpgradeDBTestCase { class UpgradeDB_321_Test extends UpgradeDBTestCase { public function prepare() {} - + /** @test */ public function placeholderForLeKioskMigrationPatch() {} } + + + + +class UpgradeDB_322_Test extends UpgradeDBTestCase { + public function prepare() { + try { + $this->query("ALTER TABLE cms_avis DROP COLUMN flags"); + } catch (Exception $e) {} + } + + + /** @test */ + public function flagsShouldBeIndexedTinyInt() { + $this->assertFieldType('cms_avis','flags', 'tinyint(4)'); + $this->assertIndex('cms_avis', 'flags', 'BTREE'); + } +} + + + + +class UpgradeDB_323_Test extends UpgradeDBTestCase { + public function prepare() { + try { + $this->query('alter table newsletters modify column titre varchar(50) not null'); + } catch(Exception $e) {} + } + + + /** @test */ + public function newslettersColumnTitreShouldBeVarchar255() { + $this->assertFieldType('newsletters', 'titre', 'varchar(255)'); + } +} diff --git a/tests/library/ZendAfi/View/Helper/TagArticleEventTest.php b/tests/library/ZendAfi/View/Helper/TagArticleEventTest.php index 99b368030ee5fc6d7fa239971934619c21958f19..3ec772945226e2ead6192a1a2d5ae8fa9bb1cf63 100644 --- a/tests/library/ZendAfi/View/Helper/TagArticleEventTest.php +++ b/tests/library/ZendAfi/View/Helper/TagArticleEventTest.php @@ -134,6 +134,17 @@ class TagArticleEventTest extends ViewHelperTestCase { } + + /** @test */ + public function withMondayThuesdayThursdayAndSaturdayPickShouldAnswersTousLesLundisMardisMercredisEtTousLesSamedi() { + $this->article + ->setEventsDebut('2011-09-05 08:00') + ->setEventsFin('2011-10-05 10:00') + ->setPickDay('1,2,4,6'); + $this->assertTagContains('Les lundis, mardis, jeudis et samedis du 5 septembre au 5 octobre 2011'); + } + + /** @test */ public function withAllDaysPickShouldAnswersTousLesJours() { $this->article