Commit eff96ddf authored by Patrick Barroca's avatar Patrick Barroca 🐧

Merge branch 'hotline' into 'master'

Hotline

See merge request !3202
parents 6229f181 cc70a529
Pipeline #8025 passed with stage
in 38 minutes and 30 seconds
29/07/2019 - v8.0.22
- ticket #80976 : Page notice : connecté en tant qu'administrateur, l'outil "Inspector Gadget" permet de supprimer un exemplaire
- ticket #95535 : Boite auteurs : meilleure prise en compte du nombre d'auteurs à afficher
- ticket #95486 : Articles, Albums et Fiches bibliothèque: les vignettes générées sont maintenant en 500px
- ticket #94048 : Administration : élargissement de la plage horaire dans le module rendez-vous
- ticket #95499 : Administration : correction d'une erreur SQL en absence de champs personnalisés dans le module rendez-vous
- ticket #90556 : Administration : correction de la mise à jour du chemin des vignettes des domaines lors du déplacement d'un fichier par l'explorateur de fichiers
- ticket #82630 : Intégrations : Ajout du dédoublonnage des notices sur le champ 001 par site
- ticket #94887 : SIGB Waterbear: correction du fonctionnement des réservations
- ticket #94527 : Liens Notices / Albums : ajout d'un script de maintenance des liens lorsque les types de documents des notices changent
23/07/2019 - v8.0.21
- ticket #89462 : Serveur OAI : Ajout d'un metadataPrefix oai_dc_bokeh plus riche que l'oai_dc pour les notices d'albums de la bibliothèque numérique Bokeh
- ticket #95222 : Ajout de la boite Auteurs
- ticket #93032 : Administration des rendez-vous : Recherche sur les champs personalisés
16/07/2019 - v8.0.20
- ticket #94707 : Bibliothèque numérique : correction de l'export EAD
......
......@@ -111,4 +111,17 @@ class Admin_RecordsController extends ZendAfi_Controller_Action {
$this->_helper->notify($this->_('La bande-annonce a bien été mise à jour'));
$this->_redirectClose($this->_getReferer());
}
public function deleteItemAction() {
if ($item = Class_Exemplaire::find($this->_getParam('id')))
$item->delete();
$this->_helper->notify($item
? $this->_('Exemplaire "%s" supprimé',
$item->getCodeBarres())
: $this->_('Exemplaire non trouvé'));
$this->_redirectToReferer();
}
}
- ticket #82630 : Ajout du dédoublonnage des notices sur le champ 001 par site.
\ No newline at end of file
- ticket #94887 : SIGB Waterbear: correction du fonctionnement des réservations
\ No newline at end of file
......@@ -739,7 +739,7 @@ class Class_Album extends Storm_Model_Abstract {
try {
$image = new Imagick($this->getVignettePath());
$image->thumbnailImage(300, 0);
$image->thumbnailImage(THUMBNAIL_FIT_WIDTH_HEIGHT, THUMBNAIL_FIT_WIDTH_HEIGHT, true, false);
if (!$image->writeImage($this->getThumbnailPath())) {
$this->addError('Erreur lors de l\'enregistrement de la vignette');
......
......@@ -318,7 +318,7 @@ class Class_AlbumRessource extends Storm_Model_Abstract {
try {
$image = $this->getImage();
$image->thumbnailImage(160, 0);
$image->thumbnailImage(THUMBNAIL_FIT_WIDTH_HEIGHT, THUMBNAIL_FIT_WIDTH_HEIGHT, true, false);
if (!$image->writeImage($this->getThumbnailPath())) {
$this->addError($this->_('Erreur lors de l\'enregistrement de la vignette'));
......
......@@ -845,7 +845,7 @@ class Class_Bib extends Storm_Model_Abstract {
try {
$image = self::getImageFactory($this->getBasePath() . $this->getFile());
$image->thumbnailImage(160, 0);
$image->thumbnailImage(THUMBNAIL_FIT_WIDTH_HEIGHT, THUMBNAIL_FIT_WIDTH_HEIGHT, true, false);
if (!$image->writeImage($this->getThumbnailPath())) {
$this->addError('Erreur lors de l\'enregistrement de la vignette');
......
......@@ -33,15 +33,15 @@ class Class_CustomField_ValueLoader extends Storm_Model_Loader {
public function findAllByInstance($instance) {
if (!$instance
|| (!$model = Class_CustomField_Model::getModel(get_class($instance))))
|| (!$model = Class_CustomField_Model::getModel(get_class($instance)))
|| (!$fields = $model->getFields()))
return [];
$fields = $model->getFields();
$field_ids = array_map(function($f) {return $f->getId();},
$fields);
return $this->findAllBy(['model_id' => $instance->getId(),
'custom_field_id' => $field_ids]);
return Class_CustomField_Value::findAllBy(['model_id' => $instance->getId(),
'custom_field_id' => $field_ids]);
}
}
......
......@@ -351,6 +351,16 @@ class Class_FRBR_Link extends Storm_Model_Abstract {
public function isSourceRecord() {
return static::TYPE_NOTICE == $this->getSourceType();
return $this->isEndRecord('source');
}
public function isTargetRecord() {
return $this->isEndRecord('target');
}
public function isEndRecord($end) {
return static::TYPE_NOTICE == $this->getTypeFor($end);
}
}
......@@ -84,9 +84,10 @@ class Class_FileManager_ModelRelation {
protected function _generateValue($model, $previous, $new) {
return $new;
return '/' . $new;
}
public function rename($path, $by) {
foreach($this->findAll($path) as $model) {
call_user_func([$model, 'callSetterByAttributeName'], $this->_field, $this->_generateValue($model, $path, $by));
......@@ -97,6 +98,7 @@ class Class_FileManager_ModelRelation {
class Class_FileManager_ModelRelationText extends Class_FileManager_ModelRelation {
protected function _generateValue($model, $previous, $new) {
return str_replace($previous, $new,
......@@ -105,6 +107,8 @@ class Class_FileManager_ModelRelationText extends Class_FileManager_ModelRelatio
}
class Class_FileManager_ModelRelationProfil {
protected $_filemanager;
......
......@@ -32,7 +32,7 @@ class Class_Notice_Thumbnail_ProviderLocal
$filename = $this->_record->getClefAlpha().'.jpg';
$image->thumbnailImage(160, 220, true, true);
$image->thumbnailImage(THUMBNAIL_FIT_WIDTH_HEIGHT, THUMBNAIL_FIT_WIDTH_HEIGHT, true, false);
try {
$image->writeImage($this->_getPath($filename));
......
......@@ -63,7 +63,7 @@ class ZendAfi_Controller_Router_RewriteWithoutBaseUrl extends Zend_Controller_Ro
*/
public function route(Zend_Controller_Request_Abstract $request) {
$path_info = $request->getPathInfo();
if (0===strpos($path_info, BASE_URL))
if ('/' != BASE_URL && 0 === strpos($path_info, BASE_URL))
$request->setPathInfo(str_replace(BASE_URL, '', $path_info));
return parent::route($request);
}
......
......@@ -36,7 +36,7 @@ class ZendAfi_Form_Admin_RendezVous extends ZendAfi_Form {
'required' => true,
'allowEmpty'=>false,
'min' => '08:00',
'max' => '18:00',
'max' => '22:00',
'step' => '5']);
$this->addElement('timePicker', 'end_time',
......@@ -44,7 +44,7 @@ class ZendAfi_Form_Admin_RendezVous extends ZendAfi_Form {
'required' => true,
'allowEmpty'=>false,
'min' => '08:00',
'max' => '18:00',
'max' => '22:00',
'step' => '5']);
$multiOptions = ['0' => $this->_('Choisir un lieu')] + Class_Lieu::getAllLibelles();
......
......@@ -20,6 +20,9 @@
*/
class ZendAfi_View_Helper_Accueil_Authors extends ZendAfi_View_Helper_Accueil_Base {
const RECORDS_LOAD_LIMIT = 500;
const AUTHORS_FETCH_BIO_LIMIT = 100;
public function getHTML() {
$this->titre = $this->preferences['titre'];
$this->contenu = $this->_renderContent();
......@@ -35,11 +38,15 @@ class ZendAfi_View_Helper_Accueil_Authors extends ZendAfi_View_Helper_Accueil_Ba
public function refreshAuthorsWithoutThumbnail() {
$authors = array_filter($this->_findAuthorsFromPreferences(),
function($author)
{
return !$author->isThumbnailValid();
});
$authors = array_slice(
array_filter($this->_findAuthorsFromPreferences(false),
function($author)
{
return !$author->isThumbnailValid();
}),
0,
static::AUTHORS_FETCH_BIO_LIMIT);
array_map(function($author)
{
(new Class_CodifAuteur_Description($author))->fetchBiography();
......@@ -74,9 +81,10 @@ class ZendAfi_View_Helper_Accueil_Authors extends ZendAfi_View_Helper_Accueil_Ba
}
protected function _findAuthorsFromPreferences() {
protected function _findAuthorsFromPreferences($with_thumbnail_only = true) {
$this->preferences['nb_notices'] = static::RECORDS_LOAD_LIMIT;
$records = Class_Notice::getNoticesFromPreferences($this->preferences);
return $this->_getAuthorsFromRecords($records);
return $this->_getAuthorsFromRecords($records, $with_thumbnail_only);
}
......@@ -95,14 +103,18 @@ class ZendAfi_View_Helper_Accueil_Authors extends ZendAfi_View_Helper_Accueil_Ba
}
protected function _getAuthorsFromRecords($records) {
$authors_ids = $this->_getAuthorsIdsFromRecords($records);
protected function _getAuthorsFromRecords($records, $with_thumbnail_only) {
if (!$authors_ids = $this->_getAuthorsIdsFromRecords($records))
return [];
$params = ['id_auteur' => $authors_ids];
if ($with_thumbnail_only) {
$params['where'] = 'thumbnail_url > \'\'';
$params['limit'] = $this->preferences['authors_count'];
}
return $authors_ids
? Class_CodifAuteur::findAllBy(['id_auteur' => array_slice($authors_ids,
0,
$this->preferences['authors_count'])])
: [];
return Class_CodifAuteur::findAllBy($params);
}
......
......@@ -152,7 +152,8 @@ class ZendAfi_View_Helper_Notice_Unimarc extends Zend_View_Helper_HtmlElement {
. $this->_tag('br');
$html .= $this->renderItem995($item)
. $this->renderItemDownload($item);
. $this->renderItemDownload($item)
. $this->renderItemDelete($item);
return $this->_tag('h3', $item->getBibLibelle() . ' ' . $item->getCodeBarres())
. $this->_tag('div', $html);
......@@ -210,6 +211,31 @@ class ZendAfi_View_Helper_Notice_Unimarc extends Zend_View_Helper_HtmlElement {
}
protected function renderItemDelete($item) {
if (!Class_Users::isCurrentUserAdmin())
return '';
$delete_url = $this->view->url(['module' => 'admin',
'controller' => 'records',
'action' => 'delete-item',
'id' => $item->getId()],
null, true);
return $this->view->tag('a',
Class_Admin_Skin::current()->renderActionIconOn('delete', $this->view) . $this->_('Supprimer l\'exemplaire'),
['style' => 'float:right;',
'onclick' => 'return confirm(\'' . $this->_('Supprimer cet exemplaire ?') . '\');',
'href' => $delete_url]);
$button = (new Class_Entity)
->setText($this->_('Supprimer l\'exemplaire'))
->setImage(Class_Admin_Skin::current()->renderActionIconOn('delete', $this->view))
->setAttribs();
return $this->view->admin_Button($button);
}
public function __call($name, $args) {
if ('visit' != substr($name, 0, 5))
throw new RuntimeException('Call to unknown method ' . get_class($this) . '::' . $name);
......
......@@ -81,7 +81,7 @@ class Bokeh_Engine {
function setupConstants() {
defineConstant('BOKEH_MAJOR_VERSION','8.0');
defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.21');
defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.22');
defineConstant('BOKEH_REMOTE_FILES', 'http://git.afi-sa.fr/afi/opacce/');
......@@ -138,6 +138,7 @@ class Bokeh_Engine {
defineConstant('MEMCACHED_PORT', '11211');
defineConstant('IMAGE_MAGICK_PATH', 'convert');
defineConstant('THUMBNAIL_FIT_WIDTH_HEIGHT', '500');
defineConstant('PATCH_PATH', ROOT_PATH . '/cosmogramme/sql/patch/');
return $this;
......
<?php
error_reporting(E_ERROR | E_PARSE);
require(__DIR__.'/../console.php');
echo "\n\nWelcome to the iRepair Album Links 3000 Pro tool by @liliputech & @patbator, since 1674 (tm) \n\n";
class Script_Album_Record_Link_Mapper {
protected $_repaired_count = 0;
public function repairedCount() {
return $this->_repaired_count;
}
public function repair($link) {
$repaired = false;
foreach(['source', 'target'] as $end)
$repaired = $repaired || $this->_repairEndIn($end, $link);
if (!$repaired) {
echo '.';
return;
}
//$link->beforeSave();
//echo json_encode($link->getRawAttributes(), JSON_PRETTY_PRINT);
//exit;
$link->save();
echo 'R';
$this->_repaired_count++;
}
protected function _repairEndIn($end, $link) {
$key = $link->getKeyFor($end);
$parts = explode('-', $key);
$type = array_pop($parts);
$truncated_key = implode('-',$parts);
if (!$link->isEndRecord($end) || Class_TypeDoc::UNKNOWN !== (int)$type)
return false;
$records = Class_Notice::findAllBy(['where' => 'clef_alpha like "' . $truncated_key . '%"']);
if (!$records || 1 < count($records))
return false;
$record = reset($records);
if ($record->isUnknown())
return false;
$link->callSetterByAttributeName($end, $record->getAbsoluteUrl());
return true;
}
}
$mapper = new Script_Album_Record_Link_Mapper();
$page = 1;
while ($links = Class_FRBR_Link::findAllBy(['limitPage' => [$page, 1000]])) {
echo "\npage: $page\n";
$page ++;
array_map([$mapper, 'repair'],
$links);
Storm_Model_Abstract::unsetLoaders();
Storm_Model_Loader::resetCache();
gc_collect_cycles();
}
echo "\n\n repaired : " . $mapper->repairedCount();
echo "\n\nDONE !!!!\n\n";
\ No newline at end of file
......@@ -932,7 +932,7 @@ class CmsControllerArticleConcertEditActionPostTest extends CmsControllerWithPer
$image = $this->mock()
->whenCalled('thumbnailImage')
->with(160, 220, true, true)
->with(500, 500, true, false)
->answers(null)
->whenCalled('writeImage')
......
......@@ -1678,7 +1678,6 @@ class FileManagerControllerWithImageInDomainTest extends FileManagerControllerTe
class FileManagerControllerMoveActionWithLinkedDataIbDBTest extends FileManagerControllerTestCase {
protected
$_domain,
$_top_profile,
$_article;
......@@ -1697,11 +1696,20 @@ class FileManagerControllerMoveActionWithLinkedDataIbDBTest extends FileManagerC
'header_img' => 'https://bokeh/userfiles/image/white.png']);
$this->_domain = $this->fixture('Class_Catalogue',
['id' => 5,
'libelle' => 'Banner domain',
'indexer' => false,
'url_img' => 'https://bokeh/userfiles/image/white.png']);
$this->fixture('Class_Catalogue',
['id' => 5,
'libelle' => 'Banner domain',
'indexer' => false,
'url_img' => 'https://bokeh/userfiles/image/white.png']);
$this->fixture('Class_Catalogue',
['id' => 6,
'libelle' => 'Other domain',
'indexer' => false,
'url_img' => '/userfiles/image/white.png']);
$disk = Class_FileManager::getFileSystem()
->whenCalled('directoryAt')
......@@ -1744,28 +1752,35 @@ class FileManagerControllerMoveActionWithLinkedDataIbDBTest extends FileManagerC
/** @test */
public function articleContentShouldHaveBeenUpdated() {
$this->dispatch('/admin/file-manager/move?item=userfiles%2Fimage%2Fwhite.png&into=userfiles', true);
$this->assertContains('userfiles/white.png', $this->_article->getContenu());
$this->assertContains('https://bokeh/userfiles/white.png', $this->_article->getContenu());
}
/** @test */
public function domainThumbnailShouldHaveBeenUpdated() {
$this->dispatch('/admin/file-manager/move?item=userfiles%2Fimage%2Fwhite.png&into=userfiles', true);
$this->assertContains('userfiles/white.png', $this->_domain->getUrlImg());
$this->assertEquals('/userfiles/white.png', Class_Catalogue::find(5)->getUrlImg());
}
/** @test */
public function otherDomainThumbnailShouldHaveBeenUpdated() {
$this->dispatch('/admin/file-manager/move?item=userfiles%2Fimage%2Fwhite.png&into=userfiles', true);
$this->assertEquals('/userfiles/white.png', Class_Catalogue::find(6)->getUrlImg());
}
/** @test */
public function profileImageShouldHaveBeenUpdated() {
$this->dispatch('/admin/file-manager/move?item=userfiles%2Fimage%2Fwhite.png&into=userfiles', true);
$this->assertContains('userfiles/white.png', $this->_top_profile->getCfgSiteParam('header_img'));
$this->assertEquals('https://bokeh/userfiles/white.png', $this->_top_profile->getCfgSiteParam('header_img'));
}
/** @test */
public function renameProfileImageShouldHaveBeenUpdated() {
$this->postDispatch('/admin/file-manager/rename?item=userfiles%2Fimage%2Fwhite.png', ['name' => 'yellow.2']);
$this->assertContains('userfiles/image/yellow.2.png', $this->_top_profile->getCfgSiteParam('header_img'));
$this->assertEquals('https://bokeh/userfiles/image/yellow.2.png', $this->_top_profile->getCfgSiteParam('header_img'));
}
......@@ -1773,7 +1788,7 @@ class FileManagerControllerMoveActionWithLinkedDataIbDBTest extends FileManagerC
public function renameProfileImageWithDoubleQuotesShouldNotBeenUpdated() {
$this->postDispatch('/admin/file-manager/rename?item=userfiles%2Fimage%2Fwhite.png&name=wrong',
['name' => 'yell"ow.2']);
$this->assertContains('userfiles/image/white.png', $this->_top_profile->getCfgSiteParam('header_img'));
$this->assertEquals('https://bokeh/userfiles/image/white.png', $this->_top_profile->getCfgSiteParam('header_img'));
}
}
......
......@@ -502,3 +502,58 @@ class RecordsControllerTrailerPostTest extends RecordsControllerTestCase {
'Le service n\'a pas répondu');
}
}
class RecordsControllerDeleteItemTest extends RecordsControllerTestCase {
public function setUp() {
parent::setUp();
$this->fixture('Class_Exemplaire',
['id' => 4,
'id_notice' => '12345',
'cote' => '234',
'code_barres' => 'ABC4' ]);
$this->dispatch('/admin/records/delete-item/id/4', true);
}
/** @test */
public function itemShouldBeDeleted() {
$this->assertNull(Class_Exemplaire::find(4));
}
/** @test */
public function responseShouldRedirectToReferer() {
$this->assertRedirect();
}
/** @test */
public function responseShouldNotifyDeletion() {
$this->assertFlashMessengerContentContains('Exemplaire "ABC4" supprimé');
}
}
class RecordsControllerDeleteInexistingItemTest extends RecordsControllerTestCase {
public function setUp() {
parent::setUp();
$this->dispatch('/admin/records/delete-item/id/4', true);
}
/** @test */
public function responseShouldRedirectToReferer() {
$this->assertRedirect();
}
/** @test */
public function responseShouldNotifyDeletion() {
$this->assertFlashMessengerContentContains('Exemplaire non trouvé');
}
}
\ No newline at end of file
......@@ -65,16 +65,37 @@ class RechercheControllerViewnoticeWithInspectorGadgetTest extends AbstractContr
['id' => 2,
'unimarc' => '',
'alpha_titre' => '',
'alpha_auteur' => '']);
$this->dispatch('/opac/recherche/viewnotice/id/2/inspector_gadget/1', true);
'alpha_auteur' => '',
'exemplaires' => [ $this->fixture('Class_Exemplaire',
['id' => 4,
'cote' => '234',
'code_barres' => 'ABC4' ]) ]]);
}
/** @test */
public function buttonNoticeBokehShouldBePresent() {
$this->dispatch('/opac/recherche/viewnotice/id/2/inspector_gadget/1', true);
$this->assertXPathContentContains('//button', 'Notice Bokeh');
}
/** @test */
public function inspectorShouldContainsButtonToDeleteItem() {
$this->dispatch('/opac/recherche/viewnotice/id/2/inspector_gadget/1', true);
$this->assertXPath('//button[contains(@onclick, "\/admin\/records\/delete-item\/id\/4")]');
}
/** @test */
public function inspectorAsRegularUserShouldNotContainsButtonToDeleteItem() {
Class_Users::getIdentity()->beModoBib();
$this->dispatch('/opac/recherche/viewnotice/id/2/inspector_gadget/1', true);
$this->assertNotXPath('//button[contains(@onclick, "\/admin\/records\/delete-item\/id\/4")]');
}
}
......
......@@ -1105,7 +1105,7 @@ class ArticleIndexAllTest extends ModelTestCase {
$image = $this->mock()
->whenCalled('thumbnailImage')
->with(160, 220, true, true)
->with(500, 500, true, false)
->answers(null)
->whenCalled('writeImage')
......
......@@ -344,7 +344,7 @@ class NoticeVignetteTest extends ModelTestCase {
->beStrict());
$image = $this->mock()
->whenCalled('thumbnailImage')
->with(160, 220, true, true)
->with(500, 500, true, false)
->answers(null)
->whenCalled('writeImage')
......
......@@ -142,7 +142,7 @@ class Class_WebService_VignetteWrongFrbrTest extends ModelTestCase {
$image = $this->mock()
->whenCalled('thumbnailImage')
->with(160, 220, true, true)
->with(500, 500, true, false)
->answers(null)
->whenCalled('writeImage')
......
......@@ -184,6 +184,7 @@ class AuthorWidgetOnPageTest extends AuthorWidgetOnPageTestCase {
{
$this->assertEquals(3, $preferences['id_panier']);
$this->assertEquals(10, $preferences['authors_count']);
$this->assertEquals(500, $preferences['nb_notices']);
$this->assertEquals(Class_Systeme_ModulesAccueil_Authors::AUTHORS_SELECTION_MODE_ALL,
$preferences['authors_selection_mode']);
return Class_Notice::findAll();
......
......@@ -190,14 +190,14 @@ class RendezVousAdminAddActionTest extends RendezVousAdminTestCase {
/** @test */
public function begintimeShouldBePresentStartAt8EndAt18() {
$this->assertXPath('//select[@name="begin_time"]//option[1][@value="08:00"]');
$this->assertXPath('//select[@name="begin_time"]//option[last()][@value="18:00"]');
$this->assertXPath('//select[@name="begin_time"]//option[last()][@value="22:00"]');
}
/** @test */
public function endtimeShouldBePresentStartAt8EndAt18() {
$this->assertXPath('//select[@name="end_time"]//option[1][@value="08:00"]');
$this->assertXPath('//select[@name="end_time"]//option[last()][@value="18:00"]');
$this->assertXPath('//select[@name="end_time"]//option[last()][@value="22:00"]');
}
......
......@@ -76,6 +76,31 @@ abstract class UsergroupAgendaAdminModoPortailLoggedTestCase extends Admin_Abstr
/** @see https://forge.afi-sa.net/issues/95499 */
class UsergroupAgendaAdminIndexWithoutCustomFieldsTest
extends UsergroupAgendaAdminModoPortailLoggedTestCase {
public function setUp() {
parent::setUp();
$groupagenda = $this->fixture('Class_UserGroup_Agenda',
['id' => 5,
'libelle' => 'MonAgenda',
'model_class' => 'Class_RendezVous']);
$this->onLoaderOfModel('Class_CustomField_Value');
$this->dispatch('/admin/usergroup-agenda');
}
/** @test */
public function shouldNotCallFindCustomFieldValues() {
$this->assertFalse(Class_CustomField_Value::methodHasBeenCalled('findAllBy'));
}
}
class UsergroupAgendaAdminIndexValidTest extends UsergroupAgendaAdminModoPortailLoggedTestCase {
public function setUp() {
parent::setUp();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment