Commit 12c56ce1 authored by Alex Arnaud's avatar Alex Arnaud

Version 7.3.1

parents f6ad272d 8a5fab84
30/07/2015 - v7.3.1
- tickets #27656, 27657 : Bibliothèque numérique 1DTouch : Prise en charge de l'authentification SSO
- ticket #27194 : Gestion des boîtes : l'ajout et la suppression de boîtes sont possibles en front
- ticket #27067 : Koha : Webservice de création des suggestions
- ticket #22209 : les utilisateurs peuvent s'abonner à un résultat de recherche via un flux atom
- ticket #27816 : "Mot de passe perdu" : Ajout d'un message indiquant à l'abonné de se rapprocher de la médiathèque si celui ci n'a pas de mail spécifié.
- ticket #27726: Empèche l'indexation des articles avec une date de fin dépassées ou un statut autre que validé
- ticket #27582: correction de la récuparation des résumés d'article de périodique.
- ticket #26977 : correction de l'url dans le titre des boites critiques et newsletters
- ticket #26909 : Visualitions des critiques : possibilité de configurer le nombre de critiques à afficher par page + ajout d'un pager
- ticket #15721 : affichage du lecteur audio dans la boite bibliotheque numerique si les ressources ne sont pas des images
20/07/2015 - v7.3.0
- ticket #24821: notification de l'abonné à la connexion sur l'expiration de son abonnement, les prêts en retard et les réservations en attente de retrait
......
# Class_Entity
## Description
In PHP we have StdClass on which we can set and get any direct property
```php
$o = new StdClass();
$o->title = 'my title';
echo $o->title; // -> my title
```
_Class_Entity_ provides same functionality with getter and setter methods
```php
$o = new Class_Entity();
$o->setTitle('my title');
echo $o->getTitle(); // -> my title
```
## Implementation
Any call to set*() will be catched to populate an internal key => value array, it will return $this to chain calls.
Any call to get*() will look for an existing key in internal array and will return its value or null if not found.
Keys of internal array are not transformed in any way
* setMyValue will produce a 'MyValue' key
* set_my_value will produce a '_my_value' key
* setmyvalue will produce a 'myvalue' key
You can define default values by setting
```php
protected $_attribs = ['MyValue' => ''];
```
Then a getMyValue() call will return an empty string instead of null if not set.
## Use cases
### In tests
When you have an API relying on getter and setter methods you can provide a _Class_Entity_ as a mock and easily verify that an attribute has been set or prepare it with attributes needed by tested code.
### In general
When you are modeling an object and don't want to write all those standard getters and setters just extend Class_Entity.
# ticket #22209
## Search result
Reification of the array returned by _Class_MoteurRecherche_ that contained queries for facets & record fetch. Now we have _Class_MoteurRecherche_Result_ that depends on search engine & search criterias. Noticeable methods:
* _recordsCollect($closure)_: for parsing all records. $closure must accept a record (_Class_Notice_).
* _acceptCriteresVisitor($visitor)_: for parsing search criterias
## Atom search feed generation
Add _ZendAfi_Feed_SearchResult_ as a _Class_MoteurRecherche_Result_ visitor that renders a search result as Atom feed.
# ticket #24821
## Notifications
......
# ticket #22209
## Search result
Reification of the array returned by _Class_MoteurRecherche_ that contained queries for facets & record fetch. Now we have _Class_MoteurRecherche_Result_ that depends on search engine & search criterias. Noticeable methods:
* _recordsCollect($closure)_: for parsing all records. $closure must accept a record (_Class_Notice_).
* _acceptCriteresVisitor($visitor)_: for parsing search criterias
## Atom search feed generation
Add _ZendAfi_Feed_SearchResult_ as a _Class_MoteurRecherche_Result_ visitor that renders a search result as Atom feed.
\ No newline at end of file
# Class_Entity
## Description
In PHP we have StdClass on which we can set and get any direct property
```php
$o = new StdClass();
$o->title = 'my title';
echo $o->title; // -> my title
```
_Class_Entity_ provides same functionality with getter and setter methods
```php
$o = new Class_Entity();
$o->setTitle('my title');
echo $o->getTitle(); // -> my title
```
## Implementation
Any call to set*() will be catched to populate an internal key => value array, it will return $this to chain calls.
Any call to get*() will look for an existing key in internal array and will return its value or null if not found.
Keys of internal array are not transformed in any way
* setMyValue will produce a 'MyValue' key
* set_my_value will produce a '_my_value' key
* setmyvalue will produce a 'myvalue' key
You can define default values by setting
```php
protected $_attribs = ['MyValue' => ''];
```
Then a getMyValue() call will return an empty string instead of null if not set.
## Use cases
### In tests
When you have an API relying on getter and setter methods you can provide a _Class_Entity_ as a mock and easily verify that an attribute has been set or prepare it with attributes needed by tested code.
### In general
When you are modeling an object and don't want to write all those standard getters and setters just extend Class_Entity.
\ No newline at end of file
- ticket #22209 : les utilisateurs peuvent s'abonner à un résultat de recherche via un flux atom
\ No newline at end of file
- ticket #27067 : Koha : Webservice de création des suggestions
\ No newline at end of file
- ticket #27194 : Gestion des boîtes : l'ajout et la suppression de boîtes sont possibles en front
\ No newline at end of file
- tickets #27656, 27657 : Bibliothèque numérique 1DTouch : Prise en charge de l'authentification SSO
\ No newline at end of file
<?php echo $this->render('modules/_debut.phtml');?>
<table>
<tr>
<td class="droite"><?php echo $this->_('Nombre affichés par page:'); ?>&nbsp;</td>
<td class="gauche"> <input name="nb_display" value="<?php echo $this->preferences['nb_display']; ?>" /></td>
</tr>
</table>
<?php echo $this->render('modules/_fin.phtml');?>
......@@ -20,6 +20,7 @@
*/
class AuthController extends ZendAfi_Controller_Action {
public function init() {
$this->view->locale = Zend_Registry::get('locale');
}
......@@ -44,7 +45,14 @@ class AuthController extends ZendAfi_Controller_Action {
return $this->_request->getParam('service');
}
public function getErrorMessages($error_code) {
$messages= [1 => $this->_('Veuillez saisir votre identifiant.'),
2 => $this->_('Identifiant inconnu.'),
4 => $this->_("Votre mail n'est pas renseigné dans votre compte lecteur. Merci de vous adresser à la bibliothèque pour connaître vos identifiants.")];
if (isset($messages[$error_code]))
return $messages[$error_code];
return '';
}
public function notify($message) {
$this->_helper->notify($message);
}
......@@ -167,7 +175,7 @@ class AuthController extends ZendAfi_Controller_Action {
$user = ZendAfi_Filters_Post::filterStatic($this->_request->getPost('username'));
$classe_user = new Class_Users();
$ret = $classe_user->lostpass($user);
$this->view->message = $this->messages[$ret["error"]];
$this->view->message = $this->getErrorMessages($ret["error"]);
$this->view->message_mail = $ret["message_mail"];
}
$this->view->username=$user;
......@@ -188,8 +196,9 @@ class AuthController extends ZendAfi_Controller_Action {
$user = ZendAfi_Filters_Post::filterStatic($this->_request->getPost('username'));
$classe_user = new Class_Users();
$ret=$classe_user->lostpass($user);
$this->view->message=$this->messages[$ret["error"]];
$this->view->message_mail=$ret["message_mail"];
$this->view->message=$this->getErrorMessages($ret["error"]);
$this->view->message_mail=isset($ret["message_mail"])?$ret["message_mail"] : '';
$this->view->username=$user;
}
}
......
......@@ -37,6 +37,7 @@ class BlogController extends ZendAfi_Controller_Action {
}
public function viewauteurAction() {
$id_user = (int)$this->_getParam('id', $this->_user->ID_USER);
if ($auteur = Class_Users::find($id_user)) {
......@@ -90,13 +91,22 @@ class BlogController extends ZendAfi_Controller_Action {
public function viewcritiquesAction() {
$this->view->page = $this->_getParam('page',1);
$id_module = (int)$this->_getParam('id_module');
$preferences = Class_Profil::getCurrentProfil()
$profil = Class_Profil::getCurrentProfil();
$preferences = $profil
->getModuleAccueilPreferences($id_module, 'CRITIQUES');
$avis = Class_AvisNotice::getAvisFromPreferences($preferences);
$this->view->config=$profil->getConfigurationOf('blog','viewcritiques','');
$avis = Class_AvisNotice::getAvisFromPreferences($preferences,[$this->view->page, $this->view->config['nb_display']]);
$this->view->nb_aff = 50;
$this->view->liste_avis = $avis;
$params_url=$this->_request->getParams();
unset($params_url['page']);
unset($params_url['current_module']);
$this->view->params_url=$params_url;
$this->view->total=count(Class_AvisNotice::getAvisFromPreferences($preferences));
$this->view->title = 'Dernières critiques';
if (array_key_exists('titre', $preferences))
$this->view->title = $preferences['titre'];
......
<?php
<?php
$this->openBoite($this->title);
if(is_array($this->liste_avis))
if(is_array($this->liste_avis))
{
$avis_to_show = array_slice($this->liste_avis, 0, $this->nb_aff);
$html_avis = array();
foreach($avis_to_show as $avis)
$html_avis = [];
foreach($this->liste_avis as $avis)
$html_avis []= $this->avis($avis);
echo implode('<div class="separator"></div>', $html_avis);
}
echo BR.'<div align="center" style="width:100%">'.$this->pager($this->total,$this->config['nb_display'],$this->page,$this->params_url ).'</div>';
$this->closeBoite();
?>
......@@ -784,7 +784,8 @@ class Class_Article extends Storm_Model_Abstract {
protected function hasToBeIndexed() {
return $this->_get('indexation') == 1;
return ($this->isVisible()
&& $this->_get('indexation') == 1);
}
......
......@@ -229,15 +229,17 @@ class Class_Newsletter extends Storm_Model_Abstract {
$vignette = $notice->fetchUrlVignette();
$resume = $notice->getResume();
$anchor_notice = $view
->getHelper('tagAnchor')
->baseURL($view->tagImg($vignette,
['style' => 'float:left;width:50px;vertical-align:top;padding:5px',
'alt' => 'vignette']
) . $title,
'recherche',
'viewnotice',
['id' => $notice->getId()]);
$anchor_notice = $view
->tagAnchor($view->absoluteUrl(
[ 'controller' => 'recherche',
'action' => 'viewnotice',
'id' => $notice->getId()]
),
$view->tagImg($vignette,
['style' => 'float:left;width:50px;vertical-align:top;padding:5px',
'alt' => 'vignette']
) . $title);
$html.=
'<div style="padding:5px">' .
......
......@@ -597,19 +597,20 @@ class Class_Notice extends Storm_Model_Abstract {
foreach ($datas as $enreg) {
if (!$enreg->getUnimarc()) continue;
$this->getNoticeUnimarc()->setNotice($enreg->getUnimarc(), 0);
$serial_article = new Class_Notice;
$serial_article->getNoticeUnimarc()->setNotice($enreg->getUnimarc(), 0);
$article = ["titre" => $this->getTitrePrincipal()];
if ($complement = $this->getComplementTitre())
$article = ["titre" => $serial_article->getTitrePrincipal()];
if ($complement = $serial_article->getComplementTitre())
$article["titre"] .= " : " . $complement;
$auteurs = $this->getAuteursUnimarc(true);
$auteurs = $serial_article->getAuteursUnimarc(true);
$article["auteur"] = isset($auteurs[0]) ? $auteurs[0] : '';
$article["pagination"] = $this->getCollation();
$note = $data = $this->get_subfield("300", "a");
$article["pagination"] = $serial_article->getCollation();
$note = $data = $serial_article->get_subfield("300", "a");
$article["note"] = isset($note[0]) ? trim($note[0]) : '';
$article["resume"] = $this->getResume();
$article["matieres"] = $this->getMatieres();
$article["resume"] = $serial_article->getResume();
$article["matieres"] = $serial_article->getMatieres();
$articles[] = $article;
}
......
......@@ -433,7 +433,8 @@ class Class_Systeme_ModulesAppli extends Class_Systeme_ModulesAbstract {
* @return array
*/
private function getDefautBlog($action) {
return array('barre_nav' => 'Critique');
return ['barre_nav' => 'Critique',
'nb_display' => 50];
}
/**
......
......@@ -971,7 +971,7 @@ class Class_Users extends Storm_Model_Abstract {
function lostpass($login) {
if(!trim($login))
return array('error' => 1);
return ['error' => 1];
if (!$user = Class_Users::getLoader()->findFirstBy(['login' => $login]))
$user = Class_UsersNonValid::getLoader()->findFirstBy(['login' => $login]);
......
......@@ -16,17 +16,25 @@
*
* 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 ZendAfi_View_Helper_Accueil_BibNumerique extends ZendAfi_View_Helper_Accueil_Base {
protected $_slideshow;
public function __construct($id_module,$params) {
parent::__construct($id_module,$params);
$this->preferences = array_merge(array('id_albums' => ''),
$this->preferences);
}
public function displayNumericRessources() {
if (!$album = Class_Album::getLoader()->find((int)$this->preferences['id_albums']))
return false;
if ($album->getImages())
return false;
$html=$this->view->renderAlbum($album);
return $html;
}
public function getSlideshow() {
if (!isset($this->_slideshow)) {
......@@ -75,15 +83,17 @@ class ZendAfi_View_Helper_Accueil_BibNumerique extends ZendAfi_View_Helper_Accue
return $this->getHtmlArray();
}
/**
* @return ZendAfi_View_Helper_Accueil_BibNumerique
*/
public function _renderAlbumTeaser() {
if ($this->isDisplayDiaporama() or $this->isDisplayListe()) {
$this->contenu .= $this->getSlideshow()->renderAlbumMedias();
} else {
$this->contenu .= sprintf('<div id="booklet_%d" class="bib-num-album"></div>',
$this->id_module);
/**
* @return ZendAfi_View_Helper_Accueil_BibNumerique
*/
public function _renderAlbumTeaser() {
if ($this->contenu = $this->displayNumericRessources())
return $this;
if ($this->isDisplayDiaporama() or $this->isDisplayListe()) {
$this->contenu .= $this->getSlideshow()->renderAlbumMedias();
} else {
$this->contenu .= sprintf('<div id="booklet_%d" class="bib-num-album"></div>',
$this->id_module);
$this->titre = $this->view->tagAnchor(array('controller' => 'bib-numerique',
'action' => 'booklet',
......
......@@ -93,16 +93,17 @@ class ZendAfi_View_Helper_Accueil_Critiques extends ZendAfi_View_Helper_Accueil_
protected function _getTitle() {
return $this->view
->getHelper('tagAnchor')
->baseURL($this->preferences['titre'],
'blog',
'viewcritiques',
['id_module' => $this->id_module,
'id_menu' => $this->_id_menu]);
}
->tagAnchor(
$this->view->url(['controller' => 'blog',
'action' => 'viewcritiques',
'id_module'=> $this->id_module,
'id_menu' => $this->_id_menu]),
$this->preferences['titre']);
}
protected function isHierarchicalDisplay() {
return '1' == $this->getPreference('hierarchical');
}
protected function isHierarchicalDisplay() {
return '1' == $this->getPreference('hierarchical');
}
}
\ No newline at end of file
......@@ -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 ZendAfi_View_Helper_TagAnchor extends Zend_View_Helper_HtmlElement {
/**
......@@ -36,10 +36,6 @@ class ZendAfi_View_Helper_TagAnchor extends Zend_View_Helper_HtmlElement {
}
public function baseURL($text, $controller, $action, $params) {
$url = 'http://' . $_SERVER['SERVER_NAME'] . BASE_URL . '/' . $controller . '/' . $action . '?' . http_build_query($params, '', '&amp;');
return $this->tagAnchor($url, $text);
}
}
?>
\ No newline at end of file
......@@ -64,7 +64,7 @@ function defineConstant($name, $value) {
function setupConstants() {
defineConstant('BOKEH_MAJOR_VERSION','7.3');
defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.0');
defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.1');
defineConstant('ROOT_PATH', realpath(dirname(__FILE__).'/..').'/');
......
......@@ -840,6 +840,8 @@ class CmsControllerArticleConcertEditArticleWithQuotesActionTest extends CmsCont
class CmsControllerArticleConcertEditActionPostTest extends CmsControllerWithPermissionTestCase {
protected $_tomorrow;
public function setUp() {
parent::setUp();
......@@ -848,6 +850,8 @@ class CmsControllerArticleConcertEditActionPostTest extends CmsControllerWithPer
Class_IntBib::beVolatile();
Class_Exemplaire::beVolatile();
$this->_tomorrow = new DateTime('tomorrow');
$this->fixture('Class_Article',
['id' => 4,
'auteur' => null,
......@@ -876,7 +880,7 @@ class CmsControllerArticleConcertEditActionPostTest extends CmsControllerWithPer
'indexation' => 1,
'id_cat' => 34,
'debut' => '01/03/2011',
'fin' => '26/03/2011',
'fin' => $this->_tomorrow->format('d-m-Y'),
'events_debut' => '02/03/2011 08:35',
'events_fin' => '05/03/2011 10:42',
'contenu' => 'Ici: <img src="../../images/bonlieu.jpg" />',
......@@ -935,8 +939,8 @@ class CmsControllerArticleConcertEditActionPostTest extends CmsControllerWithPer
/** @test */
function dateDebutShouldBe2011_03_26() {
$this->assertContains('2011-03-26', Class_Article::find(4)->getFin());
function dateFinShouldBe2011_03_26() {
$this->assertContains($this->_tomorrow->format('Y-m-d'), Class_Article::find(4)->getFin());
}
......
......@@ -412,6 +412,22 @@ class ModulesControllerConfigRechercheResultatTest extends Admin_AbstractControl
class ModulesControllerConfigViewCritiquesResultatTest extends Admin_AbstractControllerTestCase {
public function setUp() {
parent::setUp();
Class_Profil::getCurrentProfil()->setCfgModules([]);
$this->dispatch('/admin/modules/blog?config=site&type_module=blog&id_profil=2&action1=viewcritiques&action2=', true);
}
/** @test */
public function inputNumberOfCriticsDisplayOnPageShouldBe50() {
$this->assertXPath('//input[@name="nb_display"][@value="50"]');
}
}
class ModulesControllerRechercheSaisieTest extends Admin_AbstractControllerTestCase {
public function setUp() {
......
......@@ -290,8 +290,8 @@ abstract class AvisControllersFixturesTestCase extends AbonneFlorenceIsLoggedCon
$this->millenium_with_vignette->save();
$this->avis_millenium = Class_AvisNotice::newInstanceWithId(13, [
'entete' => "J'adore",
$this->avis_millenium = $this->fixture('Class_AvisNotice', ['id' => 13,
'entete' => "J'adore",
'avis' => '<div><ul><li>Suspense Intense !</li><li>Suspense Intense !</li></ul></div>',
'note' => 5,
'date_avis' => '2011-03-18 13:00:00',
......@@ -614,13 +614,15 @@ abstract class ModuleSelectionCritiquesTestCase extends AvisControllersFixturesT
$preferences = array('modules' => array(3 => array('division' => 2,
'type_module' => 'CRITIQUES',
'preferences' => array('titre' => 'Coups de coeur'))));
'preferences' => array('titre' => 'Coups de coeur'
))));
$profil = Class_Profil::getLoader()
->find(2)
->setCfgModules( ['blog' => ['viewcritiques' => ['nb_display' => 2]]])
->setCfgAccueil($preferences);
$this->_generateLoaderFor('Class_AvisNotice', array('getAvisFromPreferences'))
->expects($this->once())
$this->_generateLoaderFor('Class_AvisNotice', ['getAvisFromPreferences'])
// ->expects($this->once())
->method('getAvisFromPreferences')
->will($this->returnValue([$this->avis_millenium,
$this->avis_potter,
......@@ -645,6 +647,17 @@ class AbonneControllerAvisBlogControllerViewCritiquesTest extends ModuleSelectio
$this->assertQueryContentContains('h2', 'Potter');
}
/** @test */
public function pagerShouldBeDisplayed() {
$this->assertXPath('//a[@href="/blog/viewcritiques/id_profil/2/id_module/3/page/2"]', $this->_response->getBody());
}
/** @test */
public function pagerShouldNotContains3Pages() {
$this->assertNotXPath('//a[contains(@href,"/page/3")]', $this->_response->getBody());
}