From 25ba36a8f1e9fd1ed9516aa07b6931c0c164100d Mon Sep 17 00:00:00 2001
From: Laurent Laffont <llaffont@afi-sa.fr>
Date: Wed, 26 Apr 2017 15:56:10 +0200
Subject: [PATCH] hotline #55142 WIP new cosmo integration logs screen

---
 .../cosmo/controllers/LogsController.php      |  27 ++++
 .../cosmo/views/scripts/logs/index.phtml      |   3 +
 .../cosmo/controllers/LogsControllerTest.php  | 102 ++++++++++++
 cosmogramme/php/_menu.php                     |   2 +-
 cosmogramme/php/integre_log.php               |  18 +--
 library/Class/Admin/Skin.php                  |   8 +-
 library/ZendAfi/View/Helper/Bouton.php        |   4 +-
 library/ZendAfi/View/Helper/CosmoLogs.php     | 146 ++++++++++++++++++
 library/ZendAfi/View/Helper/Permalink.php     |   2 +-
 library/ZendAfi/View/Helper/RenderTable.php   |   2 +-
 10 files changed, 296 insertions(+), 18 deletions(-)
 create mode 100644 cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php
 create mode 100644 cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml
 create mode 100644 cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php
 create mode 100644 library/ZendAfi/View/Helper/CosmoLogs.php

diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php
new file mode 100644
index 00000000000..ccccfe88c51
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php
@@ -0,0 +1,27 @@
+<?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 Cosmo_LogsController  extends ZendAfi_Controller_Action {
+  public function indexAction() {
+  }
+}
+?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml
new file mode 100644
index 00000000000..4cb412c42f6
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml
@@ -0,0 +1,3 @@
+<?php
+echo $this->cosmoLogs();
+?>
diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php
new file mode 100644
index 00000000000..96f83429e71
--- /dev/null
+++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php
@@ -0,0 +1,102 @@
+<?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
+ */
+
+require 'application/modules/cosmo/controllers/LogsController.php';
+class LogsControllerTest  extends CosmoControllerTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    Class_CosmoVar::setValueOf('log_path','/log');
+
+    $filesystem = (new Storm_FileSystem_Volatile())
+      ->mkdir('/log')
+      ->filePutContents('/log/debug_2017-05-12.log',
+                        str_repeat('bugs bugs', 200))
+      ->filePutContents('/log/integration_2017-05-12.log',
+                        "[IntegrationTest] first line\n [IntegrationTest] second line")
+
+      ->filePutContents('/log/integration_2017-05-13.log',
+                        str_repeat('logs logs', 200000))
+      ->filePutContents('/log/debug_2017-05-13.log',
+                        "[LogTest]")
+
+      ->filePutContents('/log/a_file.log', "that should not be there");
+
+    ZendAfi_View_Helper_CosmoLogs::setFileSystem($filesystem);
+
+
+    $this->fixture('Class_Cosmogramme_Integration',
+                   ['id' => 1,
+                    'pointeur_reprise' => 1,
+                    'traite' => '2017-05-12',
+                    'nb_erreurs' => 0,
+                    'nb_warnings' => 7,
+                   ]);
+    $this->dispatch('/cosmo/logs', true);
+  }
+
+
+  /** @test */
+  public function firstTRShouldContainsSaturdayThirteenMay2017() {
+    $this->assertXPathContentContains('//table[@id="logs"]//tr[1]//td',
+                                      'samedi 13 mai 2017');
+  }
+
+
+  /** @test */
+  public function firstTRShouldContainsMagnifierIcon() {
+    $this->assertXPath('//table[@id="logs"]//tr[1]//td//img[contains(@src, "loupe")]');
+  }
+
+
+  /** @test */
+  public function firstTRReportLinkToOpenIntegrationLogShouldContaints2Mo() {
+    $this->assertXPathContentContains('//tr[1]//td//a[contains(@href, "/cosmo/logs/integration/day/2017-05-13")]',
+                                      '2 Mo');
+  }
+
+
+  /** @test */
+  public function secondTRShouldContainsFridayTwelveMay2017() {
+    $this->assertXPathContentContains('//table[@id="logs"]//tr[2]//td',
+                                      'vendredi 12 mai 2017');
+  }
+
+
+  /** @test */
+  public function secondTRReportShouldContaints59o() {
+    $this->assertXPathContentContains('//tr[2]//td', '59 o');
+  }
+
+
+  /** @test */
+  public function secondTRShouldContainsLinkToRunLogByDate() {
+    $this->assertXPath('//table[@id="logs"]//tr[2]//td//a[contains(@href, "cosmo/run-log/by-date/date/2017-05-12")]');
+  }
+
+
+  /** @test */
+  public function secondTRReportLinkToOpenDebugLogShouldContaints2Ko() {
+    $this->assertXPathContentContains('//tr[2]//td//a[contains(@href, "/cosmo/logs/debug/day/2017-05-12")]',
+                                      '2 Ko');
+  }
+}
+?>
\ No newline at end of file
diff --git a/cosmogramme/php/_menu.php b/cosmogramme/php/_menu.php
index cb7c9447f03..b6f568b20f1 100644
--- a/cosmogramme/php/_menu.php
+++ b/cosmogramme/php/_menu.php
@@ -68,7 +68,7 @@ else
 	<div class="menu_section">Intégration</div>
 	<?php
 	ligneMenu("Contrôle des intégrations","integre_controle_integrations.php");
-	ligneMenu("Journal des intégrations","integre_log.php");
+	ligneMenu("Journal des intégrations","../cosmozend/cosmo/logs");
 	ligneMenu("Traitements en cours","integre_traitements_attente.php");
 	ligneMenu("Fichiers en attente","integre_fichiers_attente.php");
 	ligneMenu("Lancer les traitements","integre_traite_main.php",true);
diff --git a/cosmogramme/php/integre_log.php b/cosmogramme/php/integre_log.php
index ee37020a43a..9caaa95b428 100644
--- a/cosmogramme/php/integre_log.php
+++ b/cosmogramme/php/integre_log.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
 include '_init_frame.php';
@@ -45,25 +45,25 @@ if($_REQUEST["log"]) {
 <?php foreach ($log->rendListe() as $lig) { ?>
 	<tr>
 	<td><?php echo rendUrlImg('loupe.png',
-													 '../cosmozend/cosmo/run-log/by-date/date/' . $lig['date_sql'], 
+													 '../cosmozend/cosmo/run-log/by-date/date/' . $lig['date_sql'],
 													 '', 'Synthèse par bibliothèques');?></td>
 	<td><?php echo $lig["date"];?></td>
 	<?php
 	// Integration
 	$url=rendUrlImg("loupe.png", "integre_log.php","log=".$lig["fic"]."&date=".$lig["date"]."&type=INTEGRATION","Afficher le détail");
-	print('<td>'. $url .'</td>');
+  print('<td>'. $url .'</td>');
 	print('<td>'. $lig["taille"] .'</td>');
-	
+
 	// Notices traitees
-	$nb=(double)$sql->fetchOne("select sum(pointeur_reprise) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'"); 
+	$nb=(double)$sql->fetchOne("select sum(pointeur_reprise) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'");
 	print('<td align="right">'. number_format($nb, 0, ',', ' ') .'</td>');
-	
+
 	// Erreurs
-	$nb=(double)$sql->fetchOne("select sum(nb_erreurs) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'"); 
+	$nb=(double)$sql->fetchOne("select sum(nb_erreurs) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'");
 	print('<td align="right">'. number_format($nb, 0, ',', ' ') .'</td>');
-	
+
 	// Warnings
-	$nb=(double)$sql->fetchOne("select sum(nb_warnings) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'"); 
+	$nb=(double)$sql->fetchOne("select sum(nb_warnings) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'");
 	print('<td align="right">'. number_format($nb, 0, ',', ' ') .'</td>');
 	print('</tr>');
 }
diff --git a/library/Class/Admin/Skin.php b/library/Class/Admin/Skin.php
index 5f9750f6115..c68af274d26 100644
--- a/library/Class/Admin/Skin.php
+++ b/library/Class/Admin/Skin.php
@@ -87,7 +87,7 @@ class Class_Admin_Skin {
   public function renderMenuIconOn($name, $view, $attribs = []) {
     $attribs = array_merge(['alt' => ''], $attribs);
 
-    if (!$src = $this->renderIconUrlOn('icons', $name))
+    if (!$src = $this->getIconUrl('icons', $name))
       return '';
 
     $attribs['src'] = $src;
@@ -98,7 +98,7 @@ class Class_Admin_Skin {
 
   public function renderActionIconOn($name, $view, $attribs = []) {
     $attribs = array_merge(['alt' => ''], $attribs);
-    $attribs['src'] = $this->renderIconUrlOn('actions', $name);
+    $attribs['src'] = $this->getIconUrl('actions', $name);
 
     return $view->tag('img', null, $attribs);
   }
@@ -107,7 +107,7 @@ class Class_Admin_Skin {
   public function renderButtonIconOn($name, $view, $attribs = []) {
     $attribs = array_merge(['alt' => ''], $attribs);
 
-    if (!$src = $this->renderIconUrlOn('buttons', $name))
+    if (!$src = $this->getIconUrl('buttons', $name))
       return '';
 
     $attribs['src'] = $src;
@@ -116,7 +116,7 @@ class Class_Admin_Skin {
   }
 
 
-  public function renderIconUrlOn($type, $name) {
+  public function getIconUrl($type, $name) {
     $config = $this->_getSkinConfig();
 
     if (!isset($config[$type][$name]))
diff --git a/library/ZendAfi/View/Helper/Bouton.php b/library/ZendAfi/View/Helper/Bouton.php
index 8d53127b23d..15a040143b8 100644
--- a/library/ZendAfi/View/Helper/Bouton.php
+++ b/library/ZendAfi/View/Helper/Bouton.php
@@ -54,7 +54,7 @@ class ZendAfi_View_Helper_Bouton extends ZendAfi_View_Helper_BaseHelper {
       $attrib = explode('=', $args[$i], 2);
       switch($attrib[0]) {
         case "id":$id=$attrib[1]; break;
-        case "picto" : $picto = Class_Admin_Skin::current()->renderIconUrlOn('buttons', $attrib[1]); break;
+        case "picto" : $picto = Class_Admin_Skin::current()->getIconUrl('buttons', $attrib[1]); break;
         case "texte"  : $texte=$attrib[1]; break;
         case "url" : $url=$attrib[1];
           $onclick="window.location.replace('".$url."')"; break;
@@ -67,7 +67,7 @@ class ZendAfi_View_Helper_Bouton extends ZendAfi_View_Helper_BaseHelper {
           if( $attrib[1]=="V")
           {
             if(!$id) $id="975";
-            $picto = Class_Admin_Skin::current()->renderIconUrlOn('buttons', 'validate');
+            $picto = Class_Admin_Skin::current()->getIconUrl('buttons', 'validate');
             if (!$texte)
               $texte = $this->translate()->_('Valider');
             if(!$largeur)
diff --git a/library/ZendAfi/View/Helper/CosmoLogs.php b/library/ZendAfi/View/Helper/CosmoLogs.php
new file mode 100644
index 00000000000..d28785dd9fe
--- /dev/null
+++ b/library/ZendAfi/View/Helper/CosmoLogs.php
@@ -0,0 +1,146 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_View_Helper_CosmoLogs extends ZendAfi_View_Helper_BaseHelper {
+  use Trait_StormFileSystem;
+
+  const DAY_LOG_REGEX ='/integration_([0-9]{4}-[0-9]{2}-[0-9]{2})\.log/';
+
+  public function cosmoLogs() {
+    $table = (new Class_TableDescription('logs'))
+          ->addColumn($this->_('Date'),
+                      ['callback' => [$this, 'renderDay'],
+                       'options' => ['data-sorter' => "false"]])
+
+          ->addColumn($this->_('Rapport'),
+                      ['callback' => [$this, 'renderReport']])
+
+          ->addColumn($this->_('Debug'),
+                      ['callback' => [$this, 'renderDebugLog']]);
+
+    return  $this->view->renderTable($table, $this->_getDays());
+  }
+
+
+  public function renderDay($day) {
+    return
+      $this->view
+      ->tagAnchor(['module' => 'cosmo',
+                   'controller' => 'run-log',
+                   'action' => 'by-date',
+                   'date' => $day->getDay()],
+
+                  Class_Admin_Skin::current()->renderActionIconOn('loupe', $this->view)
+                  . $day->getHumanDate(),
+
+                  ['title' => $this->_('Lister les intégrations du %s',
+                                       $day->getHumanDate())]);
+  }
+
+
+  public function renderReport($day) {
+    return
+      $this->view
+      ->tagAnchor(['module' => 'cosmo',
+                   'controller' => 'logs',
+                   'action' => 'integration',
+                   'day' => $day->getDay()],
+
+                  Class_Admin_Skin::current()->renderActionIconOn('loupe', $this->view)
+                  . $this->_formatFileSize($day->getIntegrationSize()),
+
+                  ['title' => $this->_('Afficher le rapport d\'intégration du %s',
+                                       $day->getHumanDate())]);
+  }
+
+
+  public function renderDebugLog($day) {
+    return
+      $this->view
+      ->tagAnchor(['module' => 'cosmo',
+                   'controller' => 'logs',
+                   'action' => 'debug',
+                   'day' => $day->getDay()],
+
+                  Class_Admin_Skin::current()->renderActionIconOn('loupe', $this->view)
+                  . $this->_formatFileSize($day->getDebugSize()),
+
+                  ['title' => $this->_('Afficher le journal technique du %s',
+                                       $day->getHumanDate())]);
+  }
+
+
+  protected function _formatFileSize($size) {
+    $units = explode(',', $this->_('o,Ko,Mo,Go'));
+    $power = $size > 0 ? floor(log($size, 1024)) : 0;
+    return round($size / pow(1024, $power)) . ' ' . $units[$power];
+  }
+
+
+  protected function _getDays() {
+    $days = $this->_filesInLogDir()
+         ->select(function ($filename) {
+                    return preg_match(static::DAY_LOG_REGEX,
+                                      $filename); })
+         ->collect(function ($filename) {
+                    return $this->_newDay($filename);
+          });
+
+    $days->uasort(function($a, $b) {
+                    return strcmp($b->getDay(),
+                                  $a->getDay()); });
+    return $days;
+  }
+
+
+  protected function _newDay($filename) {
+    $day = preg_replace(static::DAY_LOG_REGEX,
+                        '$1',
+                        $filename);
+
+    return (new Class_Entity())
+      ->setDay($day)
+      ->setHumanDate(strftime('%A %e %B %Y',  strtotime($day)))
+      ->setIntegrationSize($this->_getFileSize($filename))
+      ->setDebugSize($this->_getFileSize(str_replace('integration', 'debug', $filename)));
+  }
+
+
+  protected function _filesInLogDir() {
+    return
+      new Storm_Collection($this->getFileSystem()
+                           ->fileNamesAt($this->_getLogPath()));
+  }
+
+
+  protected function _getLogPath() {
+    return Class_CosmoVar::getValueOf('log_path');
+  }
+
+
+  protected function _getFileSize($filename) {
+    return $this->getFileSystem()
+                ->fileGetSize($this->_getLogPath() . '/' . $filename);
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Permalink.php b/library/ZendAfi/View/Helper/Permalink.php
index e1a300254b1..6f73582fd5d 100644
--- a/library/ZendAfi/View/Helper/Permalink.php
+++ b/library/ZendAfi/View/Helper/Permalink.php
@@ -24,7 +24,7 @@ class ZendAfi_View_Helper_Permalink extends ZendAfi_View_Helper_BaseHelper {
     $icon = 'reseaux/permalink.png';
     $icon_url = $profil->skinHasImage($icon)
       ? $profil->getUrlImage($icon)
-      : Class_Admin_Skin::current()->renderIconUrlOn('actions', 'permalink');
+      : Class_Admin_Skin::current()->getIconUrl('actions', 'permalink');
 
     $lien_permanent = $this->view->_('Lien permanent');
 
diff --git a/library/ZendAfi/View/Helper/RenderTable.php b/library/ZendAfi/View/Helper/RenderTable.php
index 92f431dacf6..a9777c7f634 100644
--- a/library/ZendAfi/View/Helper/RenderTable.php
+++ b/library/ZendAfi/View/Helper/RenderTable.php
@@ -27,7 +27,7 @@ class ZendAfi_View_Helper_RenderTable extends ZendAfi_View_Helper_BaseHelper {
    * @param options Array
    */
   public function renderTable($description, $grouped_models, $options = []) {
-    $grouped_models = is_array($grouped_models)
+    $grouped_models = (is_array($grouped_models) || is_a($grouped_models, 'ArrayObject'))
       ? new Class_TableDescription_Models($grouped_models)
       : $grouped_models;
 
-- 
GitLab