Browse Source

dev 2020-10

Max F 5 years ago
parent
commit
4d4f2b878d

+ 12 - 3
src/App/Middlewares/CacheHtml.php

@@ -22,11 +22,13 @@ class CacheHtml
     public function __invoke(Request $request, Response $response, callable $next)
     {
     	$request_uri = $request->SERVER['REQUEST_URI'];
+
+        $cacheable = $request->isGet();
     	
     	$cache_key = md5($request_uri);
     	$cache_file = $this->cache_dir . '/' . $cache_key . '.cache.html';
 
-    	if (is_file($cache_file) && filectime($cache_file) > time() - $this->cache_duration ) {
+    	if ($cacheable && is_file($cache_file) && filectime($cache_file) > time() - $this->cache_duration ) {
     		// Get response content from file cache
     		$content = file_get_contents($cache_file);
     		$response->setContent($content);
@@ -34,9 +36,16 @@ class CacheHtml
 
     	} else {
         	$response = $next($request, $response);
+            
+            $cacheable = $response->getAttribute('cacheable', $cacheable);
+
+            if ($cacheable) {
+            	file_put_contents($cache_file, $response->getContent());
+            	$response->addHeader('X-Cache-Html', 'miss');
 
-        	file_put_contents($cache_file, $response->getContent());
-        	$response->addHeader('X-Cache-Html', 'miss');
+            } else {
+                $response->addHeader('X-Cache-Html', 'not cacheable');
+            }
     	}
 
         return $response;

+ 47 - 1
src/App/Middlewares/DebugBar.php

@@ -10,6 +10,7 @@ use \KarmaFW\App;
 use \KarmaFW\Http\Request;
 use \KarmaFW\Http\Response;
 use \KarmaFW\App\Middlewares\DebugBar\KarmaFwCollector;
+use \KarmaFW\App\Middlewares\DebugBar\SEOCollector;
 use \KarmaFW\App\Middlewares\DebugBar\SqlDbCollector;
 use \KarmaFW\App\Middlewares\DebugBar\KarmaMessagesCollector;
 //use \KarmaFW\App\Middlewares\DebugBar\PhpTemplateCollector;
@@ -28,6 +29,7 @@ class DebugBar
 			App::setData('debugbar', $debugbar);
 			
 			$debugbar->addCollector(new KarmaFwCollector);
+			$debugbar->addCollector(new SEOCollector);
 			$debugbar->addCollector(new SqlDbCollector);
 
 			//$debugbar->addCollector(new PhpTemplateCollector); // DO NOT WORK
@@ -40,9 +42,12 @@ class DebugBar
 		$response = $next($request, $response);
 
 		$is_html = (empty($response->getContentType()) || strpos($response->getContentType(), 'text/html') === 0);
-		$show_debugbar = ($load_debugbar && $is_html);
+		$show_debugbar = ($load_debugbar && $is_html && $response->getStatus() == 200);
 
 		if ($show_debugbar) {
+
+			
+			// KarmaFW
 			$data = [
 				'app' => App::getData('app'),
 				'request' => $request,
@@ -50,6 +55,12 @@ class DebugBar
 			];
 			$debugbar['KarmaFW']->setData($data);
 
+
+			// SEO
+			$seo_data = $this->seoParseContent($response);
+			$debugbar['SEO']->setData($seo_data);
+
+
 			$response->append( $debugbarRenderer->renderHead() );
 			// TODO: $response->injectAppendTo('head', $debugbarRenderer->renderHead())
 			// => function injectAppendTo($tag) { $body = preg_replace('|</'.$tag.'>|', $injected_html . '</'.$tag.'>', $body, 1);
@@ -67,4 +78,39 @@ class DebugBar
 		return $response;
 	}
 
+
+	protected function seoParseContent(Response $response)
+	{
+		$content = $response->getBody();
+
+
+		preg_match('~<title(.*?)>(.*?)</title>~', $content, $matches);
+		$title = empty($matches) ? '' : $matches[2];
+
+		preg_match('~<meta +name="description" +content="(.*?)" *>~', $content, $matches);
+		$meta_desc = empty($matches) ? '' : $matches[1];
+
+		$x = strpos($content, '<h1');
+		$subcontent = substr($content, $x, 1024);
+		//pre($subcontent); exit;
+		//preg_match('~<h1>(.*?)</h1>~', $content, $matches);
+		preg_match('~<h1(.*?)>(.*?)</h1>~', $content, $matches);
+		//pre($matches); exit;
+		$h1 = empty($matches) ? '' : $matches[2];
+
+		preg_match_all('/<a /', $content, $matches);
+		$nb_links = empty($matches) ? 0 : count($matches[0]);
+
+
+		$data = [
+			'title' => $title,
+			'meta description' => $meta_desc,
+			'h1' => $h1,
+			'nb links' => $nb_links,
+			'content length' => strlen($content),
+		];
+
+		return $data;
+	}
+
 }

+ 37 - 0
src/App/Middlewares/DebugBar/SEOCollector.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace KarmaFW\App\Middlewares\DebugBar;
+
+use \DebugBar\DataCollector\ConfigCollector;
+
+use \KarmaFW\App;
+
+
+class SEOCollector extends ConfigCollector
+{
+	protected $data = [
+		'title' => '',
+		'meta description' => '',
+		'h1' => '',
+	];
+
+
+	public function __construct(array $data = array(), $name = 'config')
+	{
+		$data += $this->data;
+		parent::__construct($data, $name);
+	}
+
+
+    public function getName()
+    {
+        return 'SEO';
+    }
+
+    public function collect()
+    {
+        return parent::collect();
+    }
+
+}
+

+ 22 - 0
src/Http/Response.php

@@ -19,6 +19,7 @@ class Response
 	protected $redirect_url = null;
 	protected $download_file_name = null;
 	protected $download_file_path = null;
+	protected $attributes = [];
 
 
 	/* public */ const http_status_codes = [
@@ -391,4 +392,25 @@ class Response
 		return $this;
 	}
 
+
+	public function getAttributes()
+	{
+		return $this->attributes;
+	}
+
+	public function setAttributes($attributes)
+	{
+		$this->attributes = $attributes;
+	}
+
+	public function getAttribute($key, $default_value=null)
+	{
+		return isset($this->attributes[$key]) ? $this->attributes[$key] : $default_value;
+	}
+
+	public function setAttribute($key, $value)
+	{
+		$this->attributes[$key] = $value;
+	}
+
 }

+ 44 - 14
src/Templates/LightweightTemplate.php

@@ -9,9 +9,10 @@ class LightweightTemplate {
 	// https://codeshack.io/lightweight-template-engine-php/
 
 	static $blocks = array();
-	static $cache_path = APP_DIR . '/var/cache';
+	static $cache_path = APP_DIR . '/var/cache/templates';
 	static $tpl_path = APP_DIR . '/templates';
-	static $cache_enabled = (ENV == 'prod');
+	static $cache_enabled = (ENV == 'prod') || true;
+	static $tpl_last_updated = null;
 
 
 	protected $data = [];
@@ -67,20 +68,38 @@ class LightweightTemplate {
 	   	require $cached_file;
 	}
 
+
 	protected static function cache($file) {
 		if (!file_exists(self::$cache_path)) {
 		  	if (! @mkdir(self::$cache_path, 0744)) {
 		  		throw new \Exception("Cannot create templates cache dir " . self::$cache_path, 1);
 		  	}
 		}
+
 	    $cached_file = self::$cache_path . '/' . str_replace(array('/', '.html'), array('_', ''), $file . '.php');
-	    if (!self::$cache_enabled || !file_exists($cached_file) || filemtime($cached_file) < filemtime(self::$tpl_path . '/' . $file)) {
-			$code = self::includeFiles($file);
+	    $cached_file_exists = is_file($cached_file);
+
+	    if ($cached_file_exists) {
+		    $cached_file_updated = filemtime($cached_file);
+		    self::$tpl_last_updated = filemtime(self::$tpl_path . '/' . $file);
+	    } else {
+	    	$cached_file_updated = null;
+	    }
+
+	    if (ENV == 'dev') {
+	    	// on force le parcours de tous les fichiers inclus pour avoir la vraie valeur de self::$tpl_last_updated
+	    	$code = self::includeFiles($file);
+	    }
+
+	    if (!self::$cache_enabled || ! $cached_file_exists || $cached_file_updated < self::$tpl_last_updated) {
+	    	if (! isset($code)) {
+				$code = self::includeFiles($file);
+	    	}
 			$code = self::compileCode($code);
 	        file_put_contents($cached_file, '<?php class_exists(\'' . __CLASS__ . '\') or exit; ?>' . PHP_EOL . $code);
 
 	    } else {
-	    	//header('X-Template: cached');
+	    	//header('X-Template: cached'); // TODO: $response->addHeader(...)
 
 			$debugbar = App::getData('debugbar');
 			if ($debugbar) {
@@ -107,10 +126,11 @@ class LightweightTemplate {
 	protected static function compileCode($code) {
 		$code = self::compileBlock($code);
 		$code = self::compileYield($code);
+
 		$code = self::compileModules($code);
 		$code = self::compileEscapedEchos($code);
 		$code = self::compileEchos($code);
-		$code = self::compilePHP($code);
+		//$code = self::compilePHP($code);
 		return $code;
 	}
 
@@ -119,6 +139,11 @@ class LightweightTemplate {
 		$code_init = $code;
 		$layout = null;
 
+		$ts_update_file = filectime(self::$tpl_path . '/' . $file);
+		if (empty(self::$tpl_last_updated) || self::$tpl_last_updated < $ts_update_file) {
+			self::$tpl_last_updated = $ts_update_file;
+		}
+
 		static $tpl_idx = null;
 		if (is_null($tpl_idx) || (empty($caller_file) && empty($parent_file))) {
 			$tpl_idx = 0;
@@ -173,8 +198,9 @@ class LightweightTemplate {
 			$layout_code = self::includeFiles($layout, $level-1, $file);
 			$code = str_replace($value[0], '', $code);
 			
-			$layout_code = str_replace('<' . '?=$child_content?' . '>', '{$child_content}', $layout_code);
-			$layout_code = str_replace('{$child_content}', $code, $layout_code);
+			$layout_code = str_replace('<' . '?=$child_content?' . '>', '{@content}', $layout_code);
+			$layout_code = str_replace('{$child_content}', '{@content}', $layout_code);
+			$layout_code = str_replace('{@content}', $code, $layout_code);
 
 			$code = $layout_code;
 		}
@@ -214,7 +240,7 @@ class LightweightTemplate {
 
 	protected static function compileModules($code) {
 
-		// routeUrl => {url clients_list}
+		// url => {url clients_list}
 		$code = preg_replace('/{routeUrl /', '{url ', $code); // for compatibility with old templates
 		preg_match_all('~{url (.*?)}~is', $code, $matches, PREG_SET_ORDER);
 		foreach ($matches as $value) {
@@ -222,16 +248,20 @@ class LightweightTemplate {
 			$code = str_replace($value[0], getRouteUrl($value[1]), $code);
 		}
 
-		// foreach
-		preg_match_all('~{foreach ?(.*?) ?}(.*?){/foreach}~is', $code, $matches, PREG_SET_ORDER);
+		// foreach => {foreach $list as $item}<div>...</div>{/foreach}
+		preg_match_all('~{foreach (.*?) ?}(.*?){/foreach}~is', $code, $matches, PREG_SET_ORDER);
 		foreach ($matches as $value) {
 			$replaced = PHP_EOL . '<' . '?php foreach (' . $value[1] . ') : ?' . '>' . PHP_EOL . $value[2] . PHP_EOL . '<' . '?php endforeach; ?' . '>';
 			$code = str_replace($value[0], $replaced, $code);
 		}
 
-		// if
-		preg_match_all('~{if ?(.*?) ?}(.*?){/if}~is', $code, $matches, PREG_SET_ORDER);
+		// if => {if $item}<div>...</div>{/if}
+		preg_match_all('~{if (.*?) ?}(.*?){/if}~is', $code, $matches, PREG_SET_ORDER);
 		foreach ($matches as $value) {
+			
+			$replaced = '<' . '? else if ( $1 ) : ?' . '>';
+			$value[2] = preg_replace('/{elseif (.*?) ?}/', $replaced, $value[2]);
+
 			$replaced = PHP_EOL . '<' . '?php if (' . $value[1] . ') : ?' . '>' . PHP_EOL . $value[2] . PHP_EOL . '<' . '?php endif; ?' . '>';
 			$code = str_replace($value[0], $replaced, $code);
 		}
@@ -272,7 +302,7 @@ class LightweightTemplate {
 	protected static function compileYield($code) {
 		// compile yields => {yield my_block}
 		foreach(self::$blocks as $block => $value) {
-			$code = preg_replace('/{yield ?' . $block . ' ?}/', $value, $code);
+			$code = preg_replace('/{yield ' . $block . ' ?}/', $value, $code);
 		}
 		$code = preg_replace('/{yield ?(.*?) ?}/i', '', $code);
 		return $code;