diff --git a/application/modules/admin/controllers/PremierChapitreController.php b/application/modules/admin/controllers/PremierChapitreController.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8e835a8c65f03d164003cf2b57d1d6f29a39680
--- /dev/null
+++ b/application/modules/admin/controllers/PremierChapitreController.php
@@ -0,0 +1,281 @@
+<?php
+/**
+ * Copyright (c) 2015, Gael VINOT (Ville de Montrouge). 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 Admin_PremierChapitreController extends ZendAfi_Controller_Action {
+	use Trait_Translator;
+	protected $_baseUrlOptions = ['module' => 'admin', 'controller' => 'premier-chapitre'];
+
+	private $active;
+	private $pc_bib_id;
+	private	$pc_bmid;
+	private	$pc_bmkey;
+
+	private function objectsIntoArray($arrObjData, $arrSkipIndices = array()) {
+		$arrData = array();
+		// if input is object, convert into array
+		if (is_object($arrObjData)) {
+			$arrObjData = get_object_vars($arrObjData);
+		}
+		if (is_array($arrObjData)) {
+			foreach ($arrObjData as $index => $value) {
+				if (is_object($value) || is_array($value)) {
+					$value = self::objectsIntoArray($value, $arrSkipIndices); // recursive call
+				}
+				if (in_array($index, $arrSkipIndices)) {
+					continue;
+				}
+				$arrData[$index] = $value;
+			}
+		}
+		return $arrData;
+	}
+
+	public function init() {
+		parent::init();
+		$this->view->titre = 'Premier Chapitre';
+		$this->pc_bib_id = Class_AdminVar::get('PREMIERCHAPITRE_BIB_ID');
+		$this->pc_bmid = Class_AdminVar::get('PREMIERCHAPITRE_BMID');
+		$this->pc_bmkey = Class_AdminVar::get('PREMIERCHAPITRE_BMKEY');
+		$this->active = (!empty($this->pc_bib_id) && !empty($this->pc_bmid) && !empty($this->pc_bmkey));
+	}
+
+	public function preDispatch() {
+		$no_front_actions = array();
+		$request = $this->_request;
+		$action = $request->getActionName();
+		if (!$this->active && $action != 'configure' && $action != 'adminvaredit') {
+			$request->setActionName('configure');
+			$request->setDispatched(false);
+		}
+		else 
+			// Desactiver le view renderer normal
+			if (in_array($this->_request->getParam("action"),$no_front_actions)) {
+				$viewRenderer = $this->getHelper('ViewRenderer');
+				$viewRenderer->setNoRender();
+			}
+	}
+	
+	public function indexAction() {
+		$contenu .= '<ul>';
+		$contenu .= '<li><a href="/admin/premier-chapitre/configure/">Configuration</a></li>';
+		//tant que le service n'est pas configuré on n'autorise pas les actions de mise en œuvre
+		if ($this->active) {
+			$contenu .= '<li><a href="/admin/premier-chapitre/maj-ref/">Mise à jour du référentiel</a></li>';
+			$contenu .= '<li><a href="/admin/premier-chapitre/download-ref/">Téléchargement du référentiel</a></li>';
+			$contenu .= '<li><a href="/admin/premier-chapitre/maj-db/">Mise à jour de la base</a></li>';
+			$contenu .= '<li><a href="/admin/premier-chapitre/link-notices/">Lier les notices</a></li>';
+		}
+		$contenu .= '</ul>';
+		$this->view->titre .= ' :: Index des fonctions';
+		$this->view->contenu = $contenu;
+	}
+
+	function majRefAction() {
+		$data = false;
+		$pc_ws = new Class_WebService_PremierChapitre();
+		$data = $pc_ws->generate();
+		if ($data) {
+			$contenu = date('H:i:s')." Le référentiel a bien été mise à jour\n";
+			$contenu .= '<a href="/admin/premier-chapitre/download-ref/">Téléchargement du référentiel</a>';
+		}
+		else $contenu = "Une erreur est survenue\nle référentiel n'a pas pu être mis a jour\nVeuillez réessayer ultérieurement";
+		$this->view->contenu = '<pre>'.$contenu.'</pre>';
+		$this->view->contenu .= "<br/><a href='/admin/premier-chapitre/'>Retour à l'index du service Premier-chapitre</a>";
+		$this->view->titre .= ' :: Mise à jour du référentiel';
+		$this->renderScript('premier-chapitre/index.phtml');
+	}
+	function downloadRefAction() {
+		$data = false;
+		$pc_ws = new Class_WebService_PremierChapitre();
+		$data = $pc_ws->getDatafile();
+		if ($data){
+			$contenu = date('H:i:s')." Le référentiel a bien été téléchargé sur le serveur\nIl est possible de procéder à la mise à jour de la base\n";
+			$contenu .= '<a href="/admin/premier-chapitre/maj-db/">Mise à jour de la base</a>';
+		}
+		else $contenu = "Une erreur est survenue\nle référentiel n'a pas pu être téléchargé\nVeuillez réessayer ultérieurement";
+		$this->view->contenu = '<pre>'.$contenu.'</pre>';
+		$this->view->contenu .= "<br/><a href='/admin/premier-chapitre/'>Retour à l'index du service Premier-chapitre</a>";
+		$this->view->titre .= ' :: Téléchargement du référentiel';
+		$this->renderScript('premier-chapitre/index.phtml');
+	}
+
+	function majDbAction() {
+		$data = false;
+		$pc_ws = new Class_WebService_PremierChapitre();
+		$data = $pc_ws->updateDatabase();
+		if ($data) {
+			$contenu = date('H:i:s')." La base a bien été mise à jour\n";
+			$contenu .= '* '.$data['total']." oeuvres ont été lues\n";
+			if ($data['new']) $contenu .= '* '.$data['new'].(($data['new']>1)?" ont été ajoutées":" a été ajoutée")."\n";
+			if ($data['maj']) $contenu .= '* '.$data['maj'].(($data['maj']>1)?" ont été mises":" a été mise")." à jour\n";
+			if ($data['err']) $contenu .= '* '.$data['err'].(($data['err']>1)?" erreurs n'ont pas été traitées":" erreur n'a pas été traitée")."\n";
+			$contenu .= '<a href="/admin/premier-chapitre/link-notices/">Lier les notices</a>';
+		}
+		else $contenu = "Une erreur est survenue\nLa base n'a pu être mise à jour\nVeuillez réessayer ultérieurement";
+		$this->view->contenu = '<pre>'.$contenu.'</pre>';
+		$this->view->contenu .= "<br/><a href='/admin/premier-chapitre/'>Retour à l'index du service Premier-chapitre</a>";
+		$this->view->titre .= ' :: Mise à jour de la base';
+		$this->renderScript('premier-chapitre/index.phtml');
+	}
+
+	function linkNoticesAction() {
+		$data = false;
+		$pc_ws = new Class_WebService_PremierChapitre();
+		$data = $pc_ws->linkToNotices();
+		if ($data) {
+			$contenu = date('H:i:s')." Les premiers-chapitres ont bien été liés aux notices\n";
+			$contenu .= '* '.$data['total']." oeuvres ont été traités\n";
+			$contenu .= '* '.$data['maj'].(($data['maj']>1)?" ont été mises":" a été mise")." à jour\n";
+		}
+		else $contenu = "Une erreur est survenue\nLes liaisons n'ont pu être faites\nVeuillez réessayer ultérieurement";
+		$this->view->contenu = '<pre>'.$contenu.'</pre>';
+		$this->view->contenu .= "<br/><a href='/admin/premier-chapitre/'>Retour à l'index du service Premier-chapitre</a>";
+		$this->view->titre .= ' :: Liaison aux notices';
+		$this->renderScript('premier-chapitre/index.phtml');
+	}
+
+	public function configureAction() {
+		$this->view->titre .= ' :: Configuration du service';
+	Class_ScriptLoader::getInstance()
+	->loadDataTables()
+	->addJQueryReady("$('#adminvars').dataTable({ 'iDisplayLength': -1, 'bPaginate': false, 'columnDefs' : [{'orderable': false, 'targets': 2}] })")
+	->loadJQueryUI()
+	->addJQueryReady('$(document).tooltip({
+	items: "[data-tooltip]",
+	content: function() {
+		var element = $(this);
+		var html = element.find("span").html();
+	  return (html.trim() != "") ? html : "Description non disponible";
+	},
+	position: { my: "left top+30", at: "left top"},
+	hide: {duration: 1000}
+	})');
+
+		$var_connues = array('PREMIERCHAPITRE_BIB_ID', 'PREMIERCHAPITRE_BMID', 'PREMIERCHAPITRE_BMKEY');
+		$existing_variables = Class_AdminVar::findAllBy(['where'=> "CLEF like 'PREMIERCHAPITRE%'",'order' => 'CLEF']);
+		$existing_clefs = [];
+		foreach ($existing_variables as $var)
+			$existing_clefs[] = $var->getId();
+		
+		// creer les variables manquantes
+		foreach ($var_connues as $name)
+			if (!in_array($name, $existing_clefs))
+				$existing_variables[] = Class_AdminVar::set($name, '');
+
+		$table = '<table id="adminvars">
+		<thead>
+		<tr class="soustitre">
+		  <th>'.$this->traduire('Clef').'</th>
+		  <th>'.$this->traduire('Valeur').'</th>
+		  <th>'.$this->traduire('action').'</th>
+		</tr>
+		</thead>
+		<tbody>';
+		$ligne = 0;
+		foreach($existing_variables as $var) {
+			if(preg_match('^%0D%0A^',$var->getValeur()))
+				$value = urldecode(str_replace('%0D%0A','<br />',$var->getValeur()));
+			else
+				$value = urldecode($var->getValeur());
+			$ligne ++ ;
+			$table .= '<tr class="'.(($ligne & 1) ? "first" : "second").'" data-tooltip="">
+				<td style="vertical-align:top;" >'.$var->getClef().'
+					<span style="display:none;">
+						'.Class_AdminVar::helpFor($var->getClef()).'
+					</span>
+				</td>
+				<td>';
+			$table .= wordwrap($value, 35, "<br />", 1);
+			$table .='	</td>
+				<td style="width:2%;text-align:center">
+					<a data-popup="true" href="'.$this->view->url(['action' => 'adminvaredit', 'cle' => $var->getClef()]).'">'.$this->view->boutonIco("type=edit").'</a>
+				</td>
+			</tr>';
+		}
+		$table .= '</tbody></table>';
+		$this->view->contenu = $table;
+		$this->view->contenu .= "<br/><a href='/admin/premier-chapitre/'>Retour à l'index du service Premier-chapitre</a>";
+		$this->renderScript('premier-chapitre/index.phtml');
+	}
+
+	public function adminvareditAction() {
+		$id = $this->_getParam('cle');
+                $cle = Class_AdminVar::find($id);
+
+                if ($this->_request->isPost())  {
+                        $filter = new Zend_Filter_StripTags();
+                        $new_valeur = $this->_request->getPost('valeur');
+                        $cle->setValeur(trim($filter->filter($new_valeur)));
+                        $cle->save();
+                        $this->_helper->notify('Variable '.$id.' sauvegardée');
+                        $this->_redirect('admin/premier-chapitre/adminvaredit/cle/'.$id);
+                        return;
+                }
+
+                $var_valeur = $cle->getValeur();
+
+                $var_cle = $cle->getId();
+                $tuto = Class_AdminVar::helpFor($cle->getId());
+		$contenu = '<center>
+<div class="form" align="center">
+<form name="form" action="'.BASE_URL.'/admin/premier-chapitre/adminvaredit" method="post">
+<fieldset>
+<legend>'.$this->view->traduire('Variable').'</legend>
+<br />
+<div class="formTable">
+<table cellspacing="2">
+  <tr>
+    <td class="droite">'.$var_cle.'</td>
+    <td class="gauche">'.$tuto.'</td>
+  </tr>
+   <tr>
+    <td class="droite">Nouvelle valeur</td>
+    <td class="gauche"><textarea rows="10" cols="60" name="valeur">'.$var_valeur.'</textarea></td>
+  </tr>
+</table><br />
+</div>
+<input type="hidden" name="cle" value="'.$var_cle.'"/>
+</fieldset><br>
+
+<table>
+<tr>
+    <td align="right" style="padding-right:5px;">'.$this->view->bouton('type=V').' </td>
+    <td align="left" style="padding-left:5px;"> '.$this->view->bouton('id=29','picto=back.gif','texte=Retour','url='.BASE_URL.'/admin/premier-chapitre/configure','largeur=120px').'</td>
+</tr>
+</table>
+</form>
+</div>
+</center>';
+		$this->view->titre .= ' :: Modifier la variable: ' . $cle->getId();
+		$this->view->contenu = $contenu;
+		$this->renderScript('premier-chapitre/index.phtml');
+	}
+
+        public function __call($method, $args) {
+                if ('Action' == substr($method, -6)) {
+                        // Si une méthode d'action n'est pas trouvée,
+                        // rediriger vers l'action
+                        return $this->_forward('index');
+                }
+                // pour tout autre méthode, levée d'une exception
+                throw new Exception('Méthode invalide "' . $method . '" appelée',500);
+        }
+}
+?>
diff --git a/application/modules/admin/views/scripts/premier-chapitre/index.phtml b/application/modules/admin/views/scripts/premier-chapitre/index.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..984b2f459d8cc05f20361fd274da459c33c5a689
--- /dev/null
+++ b/application/modules/admin/views/scripts/premier-chapitre/index.phtml
@@ -0,0 +1,13 @@
+<div class="titre">
+	<div class="titreInner">
+		<h1><?php echo $this->escape($this->title);?></h1>
+		<div class="rss"></div>
+	</div>
+</div>
+<div class="contenu">
+  	<div class="contenuInner">
+		<div class="news-3 news">
+<?php echo $this->contenu;?>
+		</div>
+	</div>
+</div>
\ No newline at end of file
diff --git a/application/modules/opac/controllers/PremierChapitreController.php b/application/modules/opac/controllers/PremierChapitreController.php
new file mode 100644
index 0000000000000000000000000000000000000000..29b9eedfa82e714752db6335528a3068ff9c54ad
--- /dev/null
+++ b/application/modules/opac/controllers/PremierChapitreController.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Copyright (c) 2015, Gael VINOT (Ville de Montrouge). 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 PremierChapitreController extends Zend_Controller_Action {
+
+	private $active;
+	public function init() {
+		$pc_bib_id = Class_AdminVar::get('PREMIERCHAPITRE_BIB_ID');
+		$pc_bmid = Class_AdminVar::get('PREMIERCHAPITRE_BMID');
+		$pc_bmkey = Class_AdminVar::get('PREMIERCHAPITRE_BMKEY');
+		$this->active = (!empty($pc_bib_id) && !empty($pc_bmid) && !empty($pc_bmkey));
+	}
+
+	public function preDispatch() {
+		$no_front_actions = array("aleatoire", "ajout-frame");
+		$request = $this->_request;
+		$action = $request->getActionName();
+		if (!$this->active && $action != 'inactive') {
+			$request->setActionName('inactive');
+			$request->setDispatched(false); //force le rechargement du controller avec la nouvelle action
+		}
+		else {
+			// Désactiver le view renderer normal pour les éléments type blocs
+			if (in_array($this->_request->getParam("action"),$no_front_actions)) {
+				$viewRenderer = $this->getHelper('ViewRenderer');
+				$viewRenderer->setNoRender();
+			}
+		}
+	}
+
+	function inactiveAction() {
+		$this->render('inactive');
+	}
+
+	function indexAction() {
+		$html = "";
+		$this->title = "";
+		$this->view->pc_ids = Class_PremierChapitre::getAleatoire(14);
+	}
+
+	function listeCompleteAction() {
+		$pcs =  Class_PremierChapitre::getAll();
+		$html = $this->view->premierChapitre_Vignettes($pcs);
+		$this->view->title = "liste des Premiers Chapitres";
+		$this->view->contenu = $html;
+		$this->renderScript('premier-chapitre/common.phtml');
+	}
+
+	function noticeAction() {
+		$ean = $this->_request->getParam('ean');
+		$ean = Class_PremierChapitre::correct_ean($ean);
+		if ($ean) {
+			$pc = Class_PremierChapitre::findFirstBy(['ean' => $ean]);
+			if ($pc) {
+				$ntc = $pc->getNotice();
+				$url_notice = ZendAfi_View_Helper_UrlNotice::urlNotice($ntc);
+				$this->_redirect($url_notice);
+			}
+			else 
+				$this->_redirect('/');
+		}
+		else 
+			$this->_redirect('/');
+	}
+
+	function ajoutFrameAction() {
+		$params = $this->_request->getParams();
+		if (!empty($params['id_notice'])) {
+			$notice = Class_Notice::find($params['id_notice']);
+			$ean = $notice->getIsbnOrEan();
+		}
+		else {
+			$ean = (!empty($params['ean']))?$params['ean']:((!empty($params['id']))?$params['id']:"");
+		}
+		$ean = Class_PremierChapitre::getLoader()->correct_ean($ean);
+		$html = "";
+		if ($ean) {
+			$pc = Class_PremierChapitre::findFirstBy(['ean' => $ean]);
+			if (!empty($pc)) {
+				$html = $this->view->premierChapitre_Frame($pc);
+			}
+		}
+		$this->getResponse()->setHeader('Content-Type', 'text/html;charset=utf-8');
+		$this->getResponse()->setBody($html . Class_ScriptLoader::getInstance()->html());
+	}
+
+	function aleatoireAction() {
+		$nb = $this->_request->getParam('nb');
+		if (!preg_match('@^\d+$@',$nb))
+			$pcs =  Class_PremierChapitre::getAleatoire();
+		else 
+			$pcs =  Class_PremierChapitre::getAleatoire($nb);
+		$html = $this->view->premierChapitre_Vignettes($pcs);
+		$this->getResponse()->setHeader('Content-Type', 'text/html;charset=utf-8');
+		$this->getResponse()->setHeader('Pragma', 'no-cache', true);
+		$this->getResponse()->setBody($html . Class_ScriptLoader::getInstance()->html());
+	}
+
+	public function __call($method, $args) {
+		if ('Action' == substr($method, -6)) {
+			// Si une méthode d'action n'est pas trouvée,
+			// rediriger vers l'action
+			return $this->_forward('index');
+		}
+		// pour tout autre méthode, levée d'une exception
+		throw new Exception('Méthode invalide "' . $method . '" appelée',500);
+	}
+}
+?>
diff --git a/application/modules/opac/views/scripts/premier-chapitre/common.phtml b/application/modules/opac/views/scripts/premier-chapitre/common.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..2bfe9708e94778307a25d499cb068616b2783602
--- /dev/null
+++ b/application/modules/opac/views/scripts/premier-chapitre/common.phtml
@@ -0,0 +1,13 @@
+<div class="titre">
+	<div class="titreInner">
+		<h1><?php echo $this->escape($this->title);?></h1>
+		<div class="rss"></div>
+	</div>
+</div>
+<div class="contenu">
+  	<div class="contenuInner">
+		<div class="news-3 news">
+<?php echo $this->contenu;?>
+		</div>
+	</div>
+</div>
diff --git a/application/modules/opac/views/scripts/premier-chapitre/inactive.phtml b/application/modules/opac/views/scripts/premier-chapitre/inactive.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c15b626f412c7b40f8d5d9864d513115da3f91b1
--- /dev/null
+++ b/application/modules/opac/views/scripts/premier-chapitre/inactive.phtml
@@ -0,0 +1 @@
+Service inactif
diff --git a/application/modules/opac/views/scripts/premier-chapitre/index.phtml b/application/modules/opac/views/scripts/premier-chapitre/index.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..f1e43c1af948e25fae44ebae62eeda0f30342e37
--- /dev/null
+++ b/application/modules/opac/views/scripts/premier-chapitre/index.phtml
@@ -0,0 +1,18 @@
+<div class="titre">
+	<div class="titreInner">
+		<h1><?php echo $this->escape($this->title);?></h1>
+		<div class="rss"></div>
+	</div>
+</div>
+<div class="contenu">
+  	<div class="contenuInner">
+		<div class="news-3 news">
+		<div>
+			<p><img src="/public/opac/images/lireavecpremierchapitre.png" alt="premierchapitre" style="position:relative;top:-5px;"></p>
+			<p><span style="font-size:12px">Cliquez sur une couverture pour lire un extrait. Vous pouvez ensuite récupérer le livre à la bibliothèque.</span></p>
+			<p><span style="font-size:12px"><a href="/premier-chapitre/liste-complete/">Cliquez ici Pour voir la liste complète <img src="/public/opac/images/buttons/2rightarrow.png"></a></span></p>
+		</div>
+<?php echo $this->premierChapitre_Vignettes($this->pc_ids,['target' => 'frame', 'linkNotice' => 1]); ?>
+		</div>
+	</div>
+</div>
diff --git a/application/modules/opac/views/scripts/recherche/viewnotice.phtml b/application/modules/opac/views/scripts/recherche/viewnotice.phtml
index 83c3650763e512ec979767d97f0f2fd6ef8c6656..a7fda1b98e37898651559d5c44cfea00916c89d3 100644
--- a/application/modules/opac/views/scripts/recherche/viewnotice.phtml
+++ b/application/modules/opac/views/scripts/recherche/viewnotice.phtml
@@ -95,8 +95,9 @@ $script_loader = Class_ScriptLoader::getInstance()
     </div>
   </div>
 </div>
-
 <?php
+//picto premier-chapitre
+echo $this->premierChapitre_Lien($this->notice,['targetLink'=>'ancre']);
 // Entete Notice
 echo sprintf('<div class="entete_notice">%s</div>'.
 						 '<div class="flags_notice">%s</div>'.
@@ -106,6 +107,7 @@ echo sprintf('<div class="entete_notice">%s</div>'.
 						 $this->notice_Flags($this->notice, $this->preferences),
 						 $this->notice_Blocs($this->notice, $this->preferences)."<div class='clear'></div>",
 						 $this->notice_Onglets($this->notice, $this->preferences));
-
+//frame premier-chapitre
+echo '<a name="pc_ancre"></a>'.$this->premierChapitre_Frame($this->notice);
 $this->closeBoite();
 ?>
diff --git a/cosmogramme/sql/patch/patch_260.php b/cosmogramme/sql/patch/patch_260.php
new file mode 100644
index 0000000000000000000000000000000000000000..d4938cdb2eda41094d78e486942edf74d550607e
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_260.php
@@ -0,0 +1,13 @@
+<?php
+$adapter = Zend_Registry::get('sql');
+$adapter->query('CREATE TABLE IF NOT EXISTS `pc_database` ( '
+			.'`ean` varchar(17) NOT NULL, '
+			.'`url` varchar(250) NOT NULL, '
+			.'`titre` text NOT NULL, '
+			.'`auteur` text NOT NULL, '
+			.'`couverture` varchar(250) NOT NULL, '
+			.'`couverture_mini` varchar(250) NOT NULL, '
+			.'`clef_oeuvre` varchar(200) NOT NULL '
+			.') engine=MyISAM default charset=utf8;');
+$adapter->query('ALTER TABLE `pc_database` ADD PRIMARY KEY (`ean`), ADD UNIQUE KEY `ean` (`ean`);');
+?>
\ No newline at end of file
diff --git a/library/Class/Batch/PremierChapitre.php b/library/Class/Batch/PremierChapitre.php
new file mode 100644
index 0000000000000000000000000000000000000000..cbfc2bc81b3d4abb0937868a90f1545650b9d78b
--- /dev/null
+++ b/library/Class/Batch/PremierChapitre.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (c) 2015, Gaël VINOT (Ville de Montrouge). 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_Batch_PremierChapitre extends Class_Batch_RessourceNumerique{
+	protected function _getService() {
+		return new Class_WebService_PremierChapitre();
+	}
+}
+?>
\ No newline at end of file
diff --git a/library/Class/PremierChapitre.php b/library/Class/PremierChapitre.php
new file mode 100644
index 0000000000000000000000000000000000000000..b4b73109d516b82258c2547c01cad49b4fafac25
--- /dev/null
+++ b/library/Class/PremierChapitre.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Copyright (c) 2015, Gaël VINOT (Ville de Montrouge). 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 PremierChapitreLoader extends Storm_Model_Loader {
+	//nettoyage de l'entrée isbn/ean
+	public function correct_ean($isbn) {
+		$elem = new Class_Isbn($isbn);
+		$ean = $elem->getAll();
+		if ($ean['statut'] != 2) return false;
+		if (!empty($ean['ean'])) return $ean['ean'];
+		if (!empty($ean['isbn13']))	return str_replace('-','',$ean['isbn13']);
+		return false;
+	}
+	
+	public function getPremierChapitreIdsByRequete($req) {
+		if (!$req)
+			return [];
+
+		$closure = function() use ($req) {
+			return Zend_Registry::get('sql')->fetchAllByColumn($req);
+		};
+		return (new Storm_Cache())
+			->useImplodeExplodeSerialization()
+			->memoize([$req, __CLASS__, __FUNCTION__],
+								$closure);
+	}
+
+	public function findAllByRequete($req, $nb_par_page, $page_no=1 ) {
+		if (!$page_no) $page_no=1;
+		$ids = $this->getPremierChapitreIdsByRequete($req);
+		if ($nb_par_page)
+			$ids = array_slice($ids,
+					 ($page_no-1) * $nb_par_page,
+					 $nb_par_page);
+		if (empty($ids))
+			return [];
+		return $this->findAllBy(['ean' => $ids, 'order' => 'titre ASC']);
+	}
+	
+	public function getAll($nb_par_page, $page_no=1) {
+		$req = "select t.`ean` from pc_database t left join notices n on replace(n.`isbn`,'-','') = t.`ean` or n.`clef_oeuvre` = t.`clef_oeuvre` where n.`id_notice` is not null";
+		if ($nb_par_page) return $this->findAllByRequete($req,$nb_par_page,$page_no);
+		else return $this->findAllByRequete($req);
+	}
+	
+	public function getAleatoire($nb_aff) {
+		if (!$nb_aff) $nb_aff = 8;
+		$req = "select t.`ean` from pc_database t\n";
+		$req .="left join notices n on replace(n.`isbn`,'-','') = t.`ean`\n";
+		$req .= "where n.`id_notice` is not null ORDER BY RAND() LIMIT 0,".$nb_aff;
+		return $this->findAllByRequete($req);
+	}
+	
+	public function getByClef($clef) {
+		return $this->findFirstBy(['clef_oeuvre' => $clef]);
+	}
+	
+	public function getByNotice($ntc) {
+		$pc = $this->getByClef($ntc->getClefOeuvre());
+		if (!$pc) {
+			$ean = $this->correct_ean($ntc->getIsbn());
+			if ($ean) {
+				$pc = $this->findFirstBy(['ean' =>$ean]);
+				if($pc) $pc->setClefOeuvre($ntc->getClefOeuvre())->save();
+			}
+		}
+		return $pc;
+	}
+}
+
+class Class_PremierChapitre extends Storm_Model_Abstract {
+	protected $_loader_class = 'PremierChapitreLoader';
+	protected $_table_name = 'pc_database';
+	protected $_table_primary = 'ean';
+	
+	protected $_default_attribute_values = [
+		'ean' => '',
+		'url' => '',
+		'titre' => '',
+		'auteur' => '',
+		'couverture' => '',
+		'couverture_mini' => '',
+		'clef_oeuvre' => ''];
+	protected $_belongs_to = ['notice' => ['model' => 'Class_Notice', 'referenced_in' => 'clef_oeuvre']];
+	
+	public function getMiniature() {
+		return $this->getCouvertureMini();
+	}
+
+	public function getNotice() {
+		$cle = $this->getClefOeuvre();
+		if (!empty($cle)) {
+			$ntc = Class_Notice::findFirstBy(['clef_oeuvre' => $cle]);
+		}
+		else {
+			//on fait une recherche simple de la notice
+			$ntc = Class_Notice::findFirstBy(['where' => "replace(`isbn`,'-','') = '".$this->getId()."'"]);
+			if ($ntc) {
+				//on met à jour l'enregistrement premier-chapitre
+				$this->setClefOeuvre($ntc->getClefOeuvre())->save();
+			}
+		}
+		return $ntc;
+	}
+}
+?>
diff --git a/library/Class/WebService/PremierChapitre.php b/library/Class/WebService/PremierChapitre.php
new file mode 100644
index 0000000000000000000000000000000000000000..963b8d0f8f28d453838ee8a8c81c55c9aa81bf54
--- /dev/null
+++ b/library/Class/WebService/PremierChapitre.php
@@ -0,0 +1,257 @@
+<?php
+/**
+ * Copyright (c) 2015, Gaël VINOT (Ville de Montrouge). 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_WebService_PremierChapitre {// extends Class_WebService_Abstract { - on redefini l'ensemble du modele a l'identique 
+	protected $_message;
+	protected static $_http_client;
+	protected static $_auth = false;
+	protected static $_baseurl = 'http://www.premierchapitre.fr/client/';
+	protected static $_datafile = "liste_livre.xml";
+
+	private $pc_bib_id;
+	private	$pc_bmid;
+	private	$pc_bmkey;
+	
+	public function __construct() {
+		$this->pc_bib_id = Class_AdminVar::get('PREMIERCHAPITRE_BIB_ID');
+		$this->pc_bmid = Class_AdminVar::get('PREMIERCHAPITRE_BMID');
+		$this->pc_bmkey = Class_AdminVar::get('PREMIERCHAPITRE_BMKEY');
+	}
+
+	public static function setDefaultHttpClient($http_client) {
+		static::$_http_client = $http_client;
+	}
+
+	public static function getHttpClient() {
+		if (static::$_http_client==null ||  !isset(static::$_http_client)) {
+			static::$_http_client = new Zend_Http_Client(static::$_baseurl, array('keepalive' => true));
+			static::$_http_client->setCookieJar();
+		}
+		return	static::$_http_client;
+	}
+	public static function resetHttpClient() {
+		static::$_http_client = null;
+		static::$_auth = false;
+	}
+
+	public function authentify() {
+		$access_url = static::$_baseurl.'connexion/connexion.php';
+		$access_params = ["rep" => $this->pc_bib_id, "email" => $this->pc_bmid, "mdp" => $this->pc_bmkey];
+		$admin_url = static::$_baseurl.$this->pc_bib_id.'/';
+
+		if(static::$_auth == true) {
+			$data = $this->httpGet($admin_url);
+			if (preg_match('@body data-client="([^"]*)"@Usi',$data->getBody(),$m)) {
+				return static::$_auth;
+			}
+			static::$_auth = false;
+		}
+		$this->httpPost($access_url,$access_params);
+		$data = $this->httpGet($admin_url);
+		if (preg_match('@body data-client="([^"]*)"@Usi',$data->getBody(),$m)) {
+			static::$_auth = true;
+		}
+		return static::$_auth;
+	}
+	
+	public function generate() {
+		if (!$this->authentify()) {
+			throw new Exception("PremierChapitre : Erreur d'identification au service",500);
+			return false;
+		}
+		$admin_url = static::$_baseurl.$this->pc_bib_id.'/';
+		$data = $this->httpGet($admin_url);
+		if (!preg_match('@body data-client="([^"]*)"@Usi',$data->getBody(),$m)) {
+			static::$_auth = false;
+			throw new Exception("PremierChapitre : Erreur d'identification au service",500);
+			return false;
+		}
+		$clientId = $m[1];
+	        $generate_url = static::$_baseurl.'class/generation_xml.php';
+		$generate_params = ['clientId'=>$clientId,'clientRep'=>$this->pc_bib_id];
+		$data = $this->httpPost($generate_url,$generate_params);
+		//$this->setMessage("Mise à jour : ".date("d/m/Y à H:i:s"));
+		if ($data->getMessage() == "OK") return true;
+		return false;
+		//return $data;
+	}
+	public function getDatafile() {
+		if (!$this->authentify()) {
+			throw new Exception("PremierChapitre : Erreur d'identification au service",500);
+			return false;
+		}
+		$download_url = static::$_baseurl.'plugin/php_download/download.php?f=liste_livre.xml&r='.$this->pc_bib_id;
+		$data = $this->httpGet($download_url);
+		$ret = file_put_contents(static::$_datafile,$data->getBody());
+		if ($ret === false) {
+			throw new Exception("PremierChapitre : Erreur de récupération des données",500);
+			return false;
+		}
+		return true;
+	}
+	
+	public function updateDatabase() {
+		if (!file_exists(static::$_datafile)) {
+			$this->getDatafile();
+		}
+		$champs = array(
+			'ean' => '',
+			'url_reader' => 'url',
+			'titre' => '',
+			'auteur_nom' => 'auteur',
+			'url_couverture' => 'couverture',
+			'url_couverture_small' => 'couverture_mini',
+		);
+		$datas = file_get_contents(static::$_datafile);
+		$xmlObj = simplexml_load_string($datas);
+		$datas = $this->objectsIntoArray($xmlObj);
+		//on charge la base actuelle
+		$pc_all = Class_PremierChapitre::findAll();
+		$pc_db = array();
+		foreach ($pc_all as $ch) {
+			$pc_db[$ch->getId()] = $ch;
+		}
+		//on procède à la moisson : mise a jour des données existantes et ajout des nouveaux enregistrements
+		$cpt = ['maj' => 0, 'new' => 0, 'err' =>0, 'total' => count($datas['livre'])];
+		foreach ($datas['livre'] as $key => $item) {
+			//on nettoie l'ean/isbn 
+			$id = Class_PremierChapitre::correct_ean($item['ean']);
+			if ($id) {
+				$item['ean'] = $id;
+				//le document existe deja dans la base
+				if (!empty($pc_db[$id])) {
+					$m = false;
+					foreach ($champs as $k => $v) {
+						$f = $k;
+						$tmp = (!empty($item[$f]))?trim($item[$f]):'';
+						if (!empty($v)) $f = $v;
+						if ($pc_db[$id]->callGetterByAttributeName($f) != $tmp) {
+							$pc_db[$id]->callSetterByAttributeName($f,$tmp);
+							$m = true;
+						}
+					}
+					if($m) {
+						$pc_db[$id]->save();
+						$cpt['maj']++;
+					}
+				}
+				else {
+					$chap = array();
+					foreach ($champs as $k => $v) {
+						$f = $k;
+						$tmp = (!empty($item[$f]))?trim($item[$f]):'';
+						if (!empty($v)) $f = $v;
+						$chap[$f] = $tmp;
+					}
+					$cur_pc = Class_PremierChapitre::newInstance($chap);
+					$cur_pc->save();
+					$pc_db[$id] = $cur_pc;
+					$cpt['new']++;
+				}
+			}
+			else {
+				//ean incorrect on ignore
+				$cpt['err']++;
+			}
+		}
+		return $cpt;
+	}
+	
+	public function linkToNotices() {
+		$data = fetchAll("select t.`ean`, n.`clef_oeuvre` from pc_database t left join notices n on replace(n.`isbn`,'-','') = t.`ean` where n.`clef_oeuvre` is not null");
+		if (!$data)	return false;
+		$pc_all = Class_PremierChapitre::findAll();
+		$pc_db = array();
+		foreach ($pc_all as $ch) {
+			$pc_db[$ch->getId()] = $ch;
+		}
+		$cpt = ['maj' => 0, 'total' => count($data)];
+		foreach ($data as $enreg) {
+			$f = "clef_oeuvre";
+			if (!$enreg[$f]) continue;
+			$id = $enreg["ean"]; $tmp = $enreg[$f];
+			if (!empty($pc_db[$id])) {
+				if ($pc_db[$id]->callGetterByAttributeName($f) != $tmp) {
+					$pc_db[$id]->callSetterByAttributeName($f,$tmp);
+					$pc_db[$id]->save();
+					$cpt['maj']++;
+				}
+			}
+		}
+		return $cpt;
+	}
+
+	function setMessage($message) {
+		$this->_message=$message;
+	}
+	function getMessage() {
+		return $this->_message;
+	}
+
+	public function httpGet($url) {
+		$client = $this->getHttpClient();
+		$client->resetParameters();
+		$client->setUri($url);
+		return $client->request(Zend_Http_Client::GET);
+	}
+	public function httpPost($url,$params) {
+		$client = $this->getHttpClient();
+		$client->resetParameters();
+		$client->setUri($url);
+		$client->setParameterPost($params);
+		return $client->request(Zend_Http_Client::POST);
+	}
+	
+	public function isEnabled() {
+		 return ('' != trim(Class_AdminVar::get('PREMIERCHAPITRE_BIB_ID')));
+	}
+	public function getName() {
+		return 'Premier-Chapitre';
+	}
+	protected function _deleteNonHarvested() {
+		return $this;
+	}
+	private function objectsIntoArray($arrObjData, $arrSkipIndices = array()) {
+		$arrData = array();
+		// if input is object, convert into array
+		if (is_object($arrObjData)) {
+			$arrObjData = get_object_vars($arrObjData);
+		}
+		if (is_array($arrObjData)) {
+			foreach ($arrObjData as $index => $value) {
+				if (is_object($value) || is_array($value)) {
+					$value = $this->objectsIntoArray($value, $arrSkipIndices); // recursive call
+				}
+				if (in_array($index, $arrSkipIndices)) {
+					continue;
+				}
+				$arrData[$index] = $value;
+			}
+		}
+		return $arrData;
+	}
+	
+	public function update() {
+	}
+	public function harvest() {
+	}
+}
+?>
diff --git a/library/ZendAfi/View/Helper/ListeNotices/Vignettes.php b/library/ZendAfi/View/Helper/ListeNotices/Vignettes.php
index 957571966f278b012b0bf26f2ce3c904720e6abc..287af74c6e4504f2009390aff15b56c8048a2ab3 100644
--- a/library/ZendAfi/View/Helper/ListeNotices/Vignettes.php
+++ b/library/ZendAfi/View/Helper/ListeNotices/Vignettes.php
@@ -46,7 +46,8 @@ class ZendAfi_View_Helper_ListeNotices_Vignettes extends ZendAfi_View_Helper_Lis
 			. $this->_author($notice, $url_notice)
 			. $this->_docType($notice)
 			. $this->_image($notice, $preferences)
-			. $this->_info($notice, $champs);
+			. $this->_info($notice, $champs)
+			. $this->_pcTag($notice);
 
 		return $this->_tag('div', $html, ['class' => 'vignette',
 																			'data-id' => $notice->getId()]);
@@ -106,7 +107,9 @@ class ZendAfi_View_Helper_ListeNotices_Vignettes extends ZendAfi_View_Helper_Lis
 																				['entete' => str_replace('T', '', $fields)]),
 						 ['class' => 'vignette_info']);
 	}
-
+	protected function _pcTag($record) {
+		return $this->_tag('div',$this->view->premierChapitre_Lien($record),['style' => 'margin-left:70px;']);
+	}
 
 	protected function _readSpeakerTagFor($record) {
 		if (!$this->_read_speaker)
diff --git a/library/ZendAfi/View/Helper/PremierChapitre/Abstract.php b/library/ZendAfi/View/Helper/PremierChapitre/Abstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf2640317693b44fbd9c19ab13ee1dd59f1b358d
--- /dev/null
+++ b/library/ZendAfi/View/Helper/PremierChapitre/Abstract.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright (c) 2012, 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 
+ */
+abstract class ZendAfi_View_Helper_PremierChapitre_Abstract extends ZendAfi_View_Helper_BaseHelper {
+	public function loadScript(){}
+	protected function _tag($name, $content=null, $attribs=[]) {
+		$html = '<' . $name . $this->_htmlAttribs($attribs);
+		if (null === $content)
+			return $html . $this->getClosingBracket();
+		return $html . '>' . $content . '</' . $name . '>';
+	}
+	
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/PremierChapitre/Frame.php b/library/ZendAfi/View/Helper/PremierChapitre/Frame.php
new file mode 100644
index 0000000000000000000000000000000000000000..69326253fa134dfe143dbfb467a7fe2b6728452a
--- /dev/null
+++ b/library/ZendAfi/View/Helper/PremierChapitre/Frame.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright (c) 2015, Gaël VINOT (Ville de Montrouge). 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_PremierChapitre_Frame extends ZendAfi_View_Helper_PremierChapitre_Abstract {
+	public function premierChapitre_Frame($data, $preferences=[]) {
+		$this->loadScript();
+		$html = '';
+		$pc_active = new Class_WebService_PremierChapitre();
+		if (!$pc_active->isEnabled()) return $html;
+		if ($data instanceOf Class_PremierChapitre) $pc = $data;
+		else if ($data instanceOf Class_Notice) {
+			$ntc = $data;
+			$pc = Class_PremierChapitre::getByNotice($ntc);
+			if (!$pc) return $html;
+		}
+		else return $html;
+		$frm_attribs = ['id' => 'pc_frame',
+						'class' => 'iframe_premierchapitre',
+						'style' => 'width:700px; height:700px; border:none;',
+						'src' => $pc->getUrl()];
+		return $this->_tag('iframe',null,$frm_attribs);
+	}
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/PremierChapitre/Lien.php b/library/ZendAfi/View/Helper/PremierChapitre/Lien.php
new file mode 100644
index 0000000000000000000000000000000000000000..804fd80f4d0971bdd2f548bf66f89a265971b63b
--- /dev/null
+++ b/library/ZendAfi/View/Helper/PremierChapitre/Lien.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Copyright (c) 2015, Gaël VINOT (Ville de Montrouge). 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_PremierChapitre_Lien extends ZendAfi_View_Helper_PremierChapitre_Abstract {
+	private $_img = '/public/opac/images/lireavecpremierchapitre.png';
+
+	public function premierChapitre_Lien($data, $preferences=[]) {
+		$this->loadScript();
+		$html = '';
+		$pc_active = new Class_WebService_PremierChapitre();
+		if (!$pc_active->isEnabled()) return $html;
+		if ($data instanceOf Class_PremierChapitre) $pc = $data;
+		else if ($data instanceOf Class_Notice) {
+			$ntc = $data;
+			$pc = Class_PremierChapitre::getByNotice($ntc);
+			if (!$pc) return $html;
+		}
+		else return $html;
+		$lnk_attribs = [ 'id' => 'pc_lienNotice',
+						'href' => $pc->getUrl()];
+		$contenu = $this->_tag('img',null,['src' => $this->_img,
+											'style' => 'height: 30px; margin-left: 30px;']);
+		if ($preferences['linkNotice']) {
+			$lnk_attribs['href'] = '/premier-chapitre/notice/ean/'.$pc->getId();
+			$contenu = 'Voir le document';
+		}
+		else if ($preferences['targetLink'] == 'ancre' ) {
+			$lnk_attribs['href'] = '#pc_ancre';
+		}
+		
+		return $this->_tag('a',$contenu,$lnk_attribs);
+	}
+}
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/PremierChapitre/Vignettes.php b/library/ZendAfi/View/Helper/PremierChapitre/Vignettes.php
new file mode 100644
index 0000000000000000000000000000000000000000..8afecf9cae87ed486cf53c6e91d4b371d3e0ed0c
--- /dev/null
+++ b/library/ZendAfi/View/Helper/PremierChapitre/Vignettes.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright (c) 2015, Gaël VINOT (Ville de Montrouge). 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_PremierChapitre_Vignettes extends ZendAfi_View_Helper_PremierChapitre_Abstract 	  {
+	private $_imgCss = 'margin: 5px;box-sizing: border-box;box-shadow: 0 1px 2px rgba(0,0,0,.075);padding: 4px;max-height: 122px; max-width: 200px;';
+
+	public function premierChapitre_Vignettes($data, $preferences=[]) {
+		$this->loadScript();
+		$html = '';
+		$pc_active = new Class_WebService_PremierChapitre();
+		if (!$pc_active->isEnabled()) return $html;
+		$bloc_vignettes = '';
+		foreach($data as $pc) {
+			if ($preferences['target'] == 'frame')
+				$bloc_vignettes .= $this->_vignetteFrame($pc,$preferences);
+			else 
+				$bloc_vignettes .= $this->_vignetteNotice($pc,$preferences);
+		}
+		$html .= $this->_tag('div',$bloc_vignettes);
+		if ($preferences['linkNotice']) {
+			$html .= $this->_tag('div','<p></p><p>'.$this->view->premierChapitre_Lien($data[0],$preferences).'</p>');
+		}
+		if ($preferences['target'] == 'frame') {
+			$html .= $this->view->premierChapitre_Frame($data[0],$preferences);
+		}
+		return $this->_tag('div', $html);
+	}
+	
+	protected function _vignetteFrame($pc, $preferences){
+		$onclick = "\$('#pc_frame')[0].src='".$pc->getUrl()."';";
+		if($preferences['linkNotice'])
+			$onclick .= "\$('#pc_lienNotice')[0].href='/premier-chapitre/notice/ean/".$pc->getId()."';";
+		
+		$lnk_attribs = ['onclick' => $onclick,'style'=>'cursor:pointer;'];
+		return $this->_tag('a',$this->_vignetteImg($pc),$lnk_attribs);
+	}
+	
+	protected function _vignetteNotice($pc, $preferences){
+		$lnk_attribs = ['href' => '/premier-chapitre/notice/ean/"'.$pc->getId()];
+						
+		return $this->_tag('a',$this->_vignetteImg($pc),$lnk_attribs);
+	}
+	
+	protected function _vignetteImg($pc){
+		$img_attribs = ['src' => $pc->getMiniature(),
+						'alt' => $pc->getTitre().' - '.$pc->getAuteur(),
+						'title' => $pc->getTitre().' - '.$pc->getAuteur(),
+						'style' => $this->_imgCss,
+						'data-toggwle'=>"tooltip"];
+		return $this->_tag('img',null,$img_attribs);
+	}
+}
+?>
\ No newline at end of file
diff --git a/public/opac/images/lireavecpremierchapitre.png b/public/opac/images/lireavecpremierchapitre.png
new file mode 100644
index 0000000000000000000000000000000000000000..6f476daa254509ae2d77129995f1f0fa59d038f6
Binary files /dev/null and b/public/opac/images/lireavecpremierchapitre.png differ