From a391668b6e951c9d870952bed2e1f3a8d2ba31f1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Sun, 25 Feb 2018 06:09:01 +0100 Subject: [PATCH 1/1] Fix slug function Fix various spelling errors --- DataFixtures/ORM/Fixtures.php | 247 +++++++++++++++++++++++++++------- 1 file changed, 195 insertions(+), 52 deletions(-) diff --git a/DataFixtures/ORM/Fixtures.php b/DataFixtures/ORM/Fixtures.php index 109cc46..504d375 100644 --- a/DataFixtures/ORM/Fixtures.php +++ b/DataFixtures/ORM/Fixtures.php @@ -6,6 +6,10 @@ namespace AppBundle\DataFixtures\ORM; class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { public function load(\Doctrine\Common\Persistence\ObjectManager $manager) { + //Convert all title to safe slug + function slugify($str) { + return preg_replace('/[\/_|+ -]+/', '-', strtolower(trim(preg_replace('/[^a-zA-Z0-9\/_|+ -]/', '', str_replace(array('\'', '"'), ' ', iconv('UTF-8', 'ASCII//TRANSLIT', $str))), '-'))); + } //Language tree $langTree = array( 'fr' => array( @@ -61,7 +65,7 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { //Create 3 sites $sites = array(); - foreach(array('blog.rapsys.eu', 'www.rapsys.eu', 'www.aoihime.eu') as $domain) { + foreach(array('blog.rapsys.eu') as $domain) { $site = new \Rapsys\BlogBundle\Entity\Site(); $site->setDomain($domain); $site->setCreated(new \DateTime('now')); @@ -73,7 +77,7 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { //Author tree $authorTree = array( - 'Ernest Hemingway' => array( + /*'Ernest Hemingway' => array( 'fr' => 'Né le 21 juillet 1899 à Oak Park dans l\'Illinois aux États-Unis, mort le 2 juillet 1961 à Ketchum, fût un écrivain, journaliste et correspondant de guerre américain.', 'en' => 'Born on July 21, 1899 in Oak Park, Illinois, deceased on July 2, 1961 in Ketchum, was an American novelist, short story writer and journalist.' ), @@ -84,6 +88,10 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { 'George Orwell' => array( 'fr' => 'Eric Arthur Blair, né le 25 juin 1903 à Motihari pendant la période du Raj britannique et mort le 21 janvier 1950 à Londres, plus connu sous son nom de plume, est un écrivain et journaliste anglais.', 'en' => 'Eric Arthur Blair, born on June 25, 1903, deceased on January 21, 1950, better known by his pen name, was an English novelist, essayist, journalist, and critic.' + )*/ + 'raphaël g.' => array( + 'fr' => 'Raphaël G., né en 1984, est développeur web depuis 2007. Passionné par le monde du logiciel libre, depuis 2004, où il commence à contribuer à une distribution linux, connue maintenant sous le nom Mageia, un certain chemin a été parcouru dès lors.', + 'en' => 'Raphaël G., born in 1984, is a web developper since 2007. Interested in free software, since 2004, when he begin contributing to a linux distribution, known now as Mageia, some path has been traveled since then.' ) ); @@ -92,6 +100,7 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { foreach($authorTree as $name => $data) { $author = new \Rapsys\BlogBundle\Entity\Author(); $author->setName($name); + $author->setSlug(slugify($name)); $author->setCreated(new \DateTime('now')); $author->setUpdated(new \DateTime('now')); $manager->persist($author); @@ -114,18 +123,146 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { //Keyword tree $keywordTree = array( - 'disqus' => array( - 'fr' => 'Disqus', - 'en' => 'Disqus' + 'png' => array( + 'fr' => array( + 'title' => 'PNG', + 'description' => 'Le Portable Network Graphics (PNG) est un format ouvert d’images numériques, qui a été créé pour remplacer le format GIF, à l’époque propriétaire et dont la compression était soumise à un brevet' + ), + 'en' => array( + 'title' => 'PNG', + 'description' => 'Portable Network Graphics (PNG) is an raster graphics file open format that supports lossless data compression' + ) + ), + 'imagick' => array( + 'fr' => array( + 'title' => 'Imagick', + 'description' => 'Image Magick est une collection de logiciels libres pour afficher, convertir et modifier des images numériques matricielles ou vectorielles dans de nombreux formats' + ), + 'en' => array( + 'title' => 'Imagick', + 'description' => 'ImageMagick is a free and open-source software suite for displaying, converting, and editing raster image and vector image files' + ) + ), + 'image' => array( + 'fr' => array( + 'title' => 'Image', + 'description' => 'Une image est une représentation visuelle, voire mentale, de quelque chose' + ), + 'en' => array( + 'title' => 'Image', + 'description' => 'An image is an artifact that depicts visual perception, for example, a photo or a two-dimensional picture, that has a similar appearance to some subject' + ) ), 'varnish' => array( - 'fr' => 'Varnish', - 'en' => 'Varnish' + 'fr' => array( + 'title' => 'Varnish', + 'description' => 'Varnish est un serveur de cache HTTP déployé en tant que proxy inverse entre les serveurs d\'application et les clients' + ), + 'en' => array( + 'title' => 'Varnish', + 'description' => 'Varnish is an HTTP cache server deployed as a reverse proxy between applications servers and clients' + ) + ), + 'webservice' => array( + 'fr' => array( + 'title' => 'Service web', + 'description' => 'Un service web, ou service de la toile, est un protocole d\'interface informatique de la famille des technologies web permettant la communication et l\'échange de données entre applications et systèmes hétérogènes' + ), + 'en' => array( + 'title' => 'Web service', + 'description' => 'A web service is a service offered by an electronic device to another electronic device, communicating with each other via the World Wide Web' + ) + ), + 'rest' => array( + 'fr' => array( + 'title' => 'REST', + 'description' => 'Representational state transfer (REST) ou services web RESTful est une manière de fournir de l\'intéropérabilité entre systèmes d\'information sur Internet' + ), + 'en' => array( + 'title' => 'REST', + 'description' => 'Representational state transfer (REST) or RESTful web services are a way of providing interoperability between computer systems on the Internet' + ) + ), + 'hateoas' => array( + 'fr' => array( + 'title' => 'HATEOAS', + 'description' => 'HATEOAS, abréviation d\'Hypermedia As Engine of Application State, Hypermédia en tant que moteur de l\'état d\'application, constitue une contrainte de l\'architecture d\'application REST qui la distingue de la plupart des autres architectures d\'applications réseau' + ), + 'en' => array( + 'title' => 'HATEOAS', + 'description' => 'HATEOAS, abbreviation of Hypermedia As The Engine Of Application State, is a constraint of the REST application architecture that distinguishes it from other network application architectures' + ) + ), + 'uri' => array( + 'fr' => array( + 'title' => 'URI', + 'description' => 'En technologie de l\'information, une URI, abréviation d\'Uniform Resource Identifier, Identifiant uniforme de ressource, est une chaine de caractères utilisée pour identifier une ressource' + ), + 'en' => array( + 'title' => 'URI', + 'description' => 'In information technology, a Uniform Resource Identifier (URI) is a string of characters used to identify a resource' + ) ), 'cidr' => array( - 'fr' => 'Agrégation d\'adresses IP', - 'en' => 'IP addresses aggregation' + 'fr' => array( + 'title' => 'CIDR', + 'description' => 'Routage inter-domaine sans classe, de l\'anglais Classless Inter-Domain Routing, CIDR, est une méthode pour agréger des adresses IP et les router' + ), + 'en' => array( + 'title' => 'CIDR', + 'description' => 'Classless Inter-Domain Routing, CIDR, is a method for aggregating IP addresses and route them' + ) + ), + 'amazon' => array( + 'fr' => array( + 'title' => 'Amazon', + 'description' => 'Amazon Elastic Compute Cloud ou EC2 est un service proposé par Amazon permettant à des tiers de louer des serveurs sur lesquels exécuter leurs propres applications web' + ), + 'en' => array( + 'title' => 'Amazon', + 'description' => 'Amazon Elastic Compute Cloud or EC2 is an Amazon server renting service allowing third party to run their own web application' + ) + ), + 'php' => array( + 'fr' => array( + 'title' => 'PHP', + 'description' => 'PHP : Hypertext Preprocessor, plus connu sous son sigle PHP, est un langage de programmation libre, principalement utilisé pour produire des pages Web dynamiques via un serveur HTTP' + ), + 'en' => array( + 'title' => 'PHP', + 'description' => 'PHP: Hypertext Preprocessor, better known as PHP, is an open programming language, used mostly to produce dynamic web pages through an HTTP server' + ) + ), + 'mysql' => array( + 'fr' => array( + 'title' => 'MySQL', + 'description' => 'MySQL est un système de gestion de bases de données relationnelles libre' + ), + 'en' => array( + 'title' => 'MySQL', + 'description' => 'MySQL is an open-source relational database management system, RDBMS' + ) + ), + 'azure' => array( + 'fr' => array( + 'title' => 'Azure', + 'description' => 'Microsoft Azure, anciennement Windows Azure, est une plateforme applicative en nuage crée par Microsoft pour construire, tester, déployer et gérer des applications et services sur un réseau global de centres de données opéré par Microsoft' + ), + 'en' => array( + 'title' => 'Azure', + 'description' => 'Microsoft Azure, formerly Windows Azure, is a cloud computing service created by Microsoft for building, testing, deploying, and managing applications and services through a global network of Microsoft-managed data centers' + ) ), + 'microsoft' => array( + 'fr' => array( + 'title' => 'Microsoft', + 'description' => 'Microsoft Corporation est une multinationale informatique et micro-informatique américaine, fondée en 1975 par Bill Gates et Paul Allen' + ), + 'en' => array( + 'title' => 'Microsoft', + 'description' => 'Microsoft Corporation is an american multinational technology company, founded in 1975 by Bill Gates and Paul Allen' + ) + ) ); //Create 3 keywords @@ -137,10 +274,12 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { $manager->persist($keyword); //Flush to get the id $manager->flush(); - $keywords[] = $keyword; - foreach($data as $lang => $title) { + $keywords[$name] = $keyword; + foreach($data as $lang => $datas) { $keywordTranslation = new \Rapsys\BlogBundle\Entity\KeywordTranslation(); - $keywordTranslation->setTitle($title); + $keywordTranslation->setTitle($datas['title']); + $keywordTranslation->setSlug(slugify($datas['title'])); + $keywordTranslation->setDescription($datas['description']); $keywordTranslation->setKeyword($keyword); $keywordTranslation->setKeywordId($keyword->getId()); $keywordTranslation->setLanguage($languages[$lang]); @@ -155,6 +294,7 @@ class Fixtures extends \Doctrine\Bundle\FixturesBundle\Fixture { //Article tree $articleTree = array( array( + 'keywords' => array('image', 'imagick', 'png'), 'fr' => array( 'title' => 'Comment détecter la tranparence dans des images PNG en PHP de manière fiable', 'description' => 'J\'ai récemment du trouver comment détecter en PHP les images PNG transparentes. @@ -193,26 +333,26 @@ function png_has_transparency($im) { } [/code] -Cette fonction fonctionne avec les deux seules possibilitées : PNG 32bit et 8bit. +Cette fonction fonctionne avec les deux seules possibilités : PNG 8 et 32 bits. -Le premier cas est un PNG 32bit avec transparence activé, on doit alors vérifier l\'opacité de chaque pixel savoir si l\'image a de la transparence ou non. +Le premier cas est un PNG 32 bits avec transparence activée, on doit alors vérifier l\'opacité de chaque pixel savoir si l\'image a de la transparence ou non. -Le second cas est un PNG 8 bit, on a simplement à détecter un marqueur de transparence dans le contenu du fichier. +Le second cas est un PNG 8 bits, on a simplement à détecter un marqueur de transparence dans le contenu du fichier. -Dans cette configuration de fonction, on lit seulement une partie du PNG 32bit jusqu\'à détection d\'un pixel transparent ou on analyse le contenu jusqu\'à trouver un marqueur de transparence dans un PNG 8bit. +Dans cette configuration de fonction, on lit seulement une partie du PNG 32 bits jusqu\'à détection d\'un pixel transparent où on analyse le contenu jusqu\'à trouver un marqueur de transparence dans un PNG 8 bits. -Les pires cas seront un PNG 32bit avec marqueur de transparence sans pixel transparent ou PNG 8bit sans marqueur de transparence. +Les pires cas seront un PNG 32 bits avec marqueur de transparence sans pixel transparent ou PNG 8 bits sans marqueur de transparence. Selon les probabilités de rencontrer les différents cas de transparence vous pouvez être intéressé pour renverser l\'ordre des tests de cette fonction. -Un grand merci à ces articles qui expliquent plus en détail comment fonctionne les différentes parties de ce code: +Un grand merci à ces articles qui expliquent plus en détail comment fonctionnent les différentes parties de ce code: [ul] -[li]https://www.jonefox.com/blog/2011/04/15/how-to-detect-transparency-in-png-images/[/li] -[li]http://camendesign.com/code/uth1_is-png-32bit[/li] -[li]https://stackoverflow.com/questions/5495275/how-to-check-if-an-image-has-transparency-using-gd[/li] +[li][url]https://www.jonefox.com/blog/2011/04/15/how-to-detect-transparency-in-png-images[/url][/li] +[li][url]http://camendesign.com/code/uth1_is-png-32bit[/url][/li] +[li][url]https://stackoverflow.com/questions/5495275/how-to-check-if-an-image-has-transparency-using-gd[/url][/li] [/ul] -En espérant que ça aidera quelqu\'un quelque part.' +En espérant que cela puisse aider quelques personnes.' ), 'en' => array( 'title' => 'How to reliably detect PNG image transparency with PHP', @@ -228,7 +368,7 @@ function png_has_transparency($im) { //Retrieve content from imagick object $content = $im->getImageBlob(); - //Detect 32bit png (each pixel has tranparency level) + //Detect 32-bit png (each pixel has tranparency level) if (ord(substr($content, 25, 1)) & 4) { //Fetch iterator $p = $im->getPixelIterator(); @@ -243,7 +383,7 @@ function png_has_transparency($im) { } } } - //Check 8bit png transparency + //Check 8-bit png transparency } elseif (stripos($content, \'PLTE\') !== false || stripos($content, \'tRNS\') !== false) { return true; } @@ -253,38 +393,39 @@ function png_has_transparency($im) { } [/code] -This function works with the only two transparency possibilities: 32bit and 8bit PNG. +This function works with the only two transparency possibilities: 8 and 32-bit PNG. -The first case is a 32bit PNG with transparency enabled, we have then to check every pixel to detect if it has transparent part or not. +The first case is a 32-bit PNG with transparency enabled, we have then to check every pixel to detect if it has transparent part or not. -The second case is a 8bit PNG, then we only have to look the file content for transparency markers. +The second case is a 8-bit PNG, then we only have to look the file content for transparency markers. -In this function configuration, we only read part of the file in 32bit PNG until we detect one transparent pixel or parse content until transparency marker is detected in 8bit PNG. +In this function configuration, we only read part of the file in 32-bit PNG until we detect one transparent pixel or parse content until transparency marker is detected in 8-bit PNG. -The worst case scenario will be 32bit PNG with transparency flag without transparency or 8bit PNG without transparency flag. +The worst case scenario will be 32-bit PNG with transparency flag without transparency or 8-bit PNG without transparency flag. Depending on how likely you are to have transparency in each cases you might want to reverse the flow of this function. Big thanks to these articles which expains how these parts work in a bit more detail: [ul] -[li]https://www.jonefox.com/blog/2011/04/15/how-to-detect-transparency-in-png-images/[/li] -[li]http://camendesign.com/code/uth1_is-png-32bit[/li] -[li]https://stackoverflow.com/questions/5495275/how-to-check-if-an-image-has-transparency-using-gd[/li] +[li][url]https://www.jonefox.com/blog/2011/04/15/how-to-detect-transparency-in-png-images[/url][/li] +[li][url]http://camendesign.com/code/uth1_is-png-32bit[/url][/li] +[li][url]https://stackoverflow.com/questions/5495275/how-to-check-if-an-image-has-transparency-using-gd[/url][/li] [/ul] Hope this helps someone else out there.' ) ), array( + 'keywords' => array('hateoas', 'rest', 'uri', 'varnish', 'webservice'), 'fr' => array( 'title' => 'Mise en cache de webservice avec varnish', - 'description' => 'J\'ai eu récemment à trouver comment mettre en cache les réponse d\'un webservice. + 'description' => 'J\'ai eu récemment à trouver comment mettre en cache les réponses d\'un webservice. Voici la configuration varnish qui a répondu à mes besoins.', - 'body' => 'J\'ai eu récemment à trouver comment mettre en cache les réponse d\'un webservice. + 'body' => 'J\'ai eu récemment à trouver comment mettre en cache les réponses d\'un webservice. L\'API RESTfull du webservice sert de passerelle entre un API privé HATEOAS et un client générant plus de 500 000 requêtes par jour. -La première surprise est qu\'un client bien élevé, envoyant un en-tête Authorization: Bearer , ne sera pas mis en cache par Varnish par défaut ! +La première surprise est qu\'un client bien élevé, envoyant un en-tête Authorization: Bearer, ne sera pas mis en cache par Varnish par défaut ! Forçons le fonctionnement standard avec l\'en-tête pour le préfixe de l\'uri de notre webservice: [code=varnish] @@ -298,9 +439,9 @@ sub vcl_recv { } [/code] -Ce changement a des conséquences sur la sécurité, n\'importe qui autorisé à interroger Varnish sera en mesure de récupérer un résultat en cache sans s\'identifier. +Ce changement a des conséquences sur la sécurité, puisque n\'importe quelle personne autorisée à interroger Varnish sera en mesure de récupérer un résultat en cache sans s\'identifier. -Il peut être une bonne idée de valider la valeur de l\'en-tête Authorization avant de fournir le résultat en cache. +Il est important de valider la valeur de l\'en-tête Authorization avant de fournir le résultat depuis le cache. Notre webservice a trois réponses possibles : [ul] @@ -326,8 +467,7 @@ sub vcl_fetch { } [/code] -Avec cette configuration, on a divisé par 5 la quantité de demandes sur notre passerelle -pour le client qui n\'était pas en mesure de mettre en cache lui-même nos résultats.' +Avec cette configuration, on a divisé par 5 la quantité de demandes sur notre passerelle pour le client qui n\'était pas en mesure de mettre en cache lui-même nos résultats.' ), 'en' => array( 'title' => 'Caching webservice with varnish', @@ -337,7 +477,7 @@ Here is the Varnish configuration fitting my needs.', The webservice is a RESTfull API serving as a gateway between a private HATEOAS API and a client generating more than 500 000 requests a day. -The first surprise is that if your well educated client, sending you a header Authorization: Bearer , will not be cached by default by Varnish ! +The first surprise is that if your well educated client, sending you a header Authorization: Bearer, will not be cached by default by Varnish ! Let\'s force back the standard behaviour with this header for our webservice uri prefix: [code=varnish] @@ -351,9 +491,9 @@ sub vcl_recv { } [/code] -This has security implication, now anyone allowed to request varnish will be able to retrieve a cached result without authentification. +This has security implication, because anyone allowed to request varnish will be able to retrieve a cached result without authentification. -It may be a good idea to validate the Authorization header value before serving the cached result. +It is important to validate the Authorization header value before serving the result from cache. Now, our webservice has three possibles answers : [ul] @@ -379,14 +519,13 @@ sub vcl_fetch { } [/code] -With this configuration, we divided by 5 the quantity of request on our gateway -from the client who was not able to cache our result himself.' +With this configuration, we divided by 5 the quantity of request on our gateway from the client who was not able to cache our result himself.' ) ), array( + 'keywords' => array('amazon', 'azure', 'cidr', 'microsoft', 'mysql', 'php', 'webservice'), 'fr' => array( 'title' => 'Gestion des plages d\'IP en PHP/MySQL', - 'description' => 'J\'ai récemment du ', 'description' => 'J\'ai eu récemment à trouver comment restreindre l\'accès à un service en ligne à certaines plages d\'IP. Voici la solution qui a répondu à mes besoins.', 'body' => 'J\'ai récemment du autoriser l\'accès à un service en ligne à seulement quelques plages d\'IP. @@ -464,8 +603,8 @@ s)) { Urls pour les plages d\'IP de Microsoft Azure : [ul] -[li]https://www.microsoft.com/en-us/download/details.aspx?id=41653[/li] -[li]https://msdn.microsoft.com/library/mt757330.aspx[/li] +[li][url]https://www.microsoft.com/en-us/download/details.aspx?id=41653[/url][/li] +[li][url]https://msdn.microsoft.com/library/mt757330.aspx[/url][/li] [/ul]' ), 'en' => array( @@ -548,8 +687,8 @@ s)) { Microsoft Azure Ip ranges urls: [ul] -[li]https://www.microsoft.com/en-us/download/details.aspx?id=41653[/li] -[li]https://msdn.microsoft.com/library/mt757330.aspx[/li] +[li][url]https://www.microsoft.com/en-us/download/details.aspx?id=41653[/url][/li] +[li][url]https://msdn.microsoft.com/library/mt757330.aspx[/url][/li] [/ul]' ) ), @@ -560,9 +699,12 @@ Microsoft Azure Ip ranges urls: $article = new \Rapsys\BlogBundle\Entity\Article(); $article->setCreated(new \DateTime('now')); $article->setUpdated(new \DateTime('now')); - $article->addKeyword($keywords[$i]); - $article->setSite($sites[$i]); - $article->setAuthor($authors[$i]); + foreach($data['keywords'] as $keyword) { + $article->addKeyword($keywords[$keyword]); + } + unset($data['keywords']); + $article->setSite($sites[0]); + $article->setAuthor($authors[0]); $manager->persist($article); //Flush to get the id $manager->flush(); @@ -570,6 +712,7 @@ Microsoft Azure Ip ranges urls: foreach($data as $lang => $datas) { $articleTranslation = new \Rapsys\BlogBundle\Entity\ArticleTranslation(); $articleTranslation->setTitle($datas['title']); + $articleTranslation->setSlug(slugify($datas['title'])); $articleTranslation->setDescription($datas['description']); $articleTranslation->setBody($datas['body']); $articleTranslation->setArticle($article); -- 2.41.1