From 47851aa99a2fb8bb1e4ba4327e7674b756e34b48 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Mon, 8 Mar 2021 11:13:19 +0100 Subject: [PATCH 01/12] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'README.md'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 54fc703b..cb8fa959 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# ZwiiCMS 10.4.05 +# ZwiiCMS 10.5.00 Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation. From a7498110fb583093534d5e0ed5770874ba1f3368 Mon Sep 17 00:00:00 2001 From: SylvainLelievre Date: Tue, 9 Mar 2021 14:26:09 +0100 Subject: [PATCH 02/12] Correction dossier pour l'image du flux RSS --- module/blog/view/index/index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/blog/view/index/index.php b/module/blog/view/index/index.php index ca0f24d7..7beeb709 100755 --- a/module/blog/view/index/index.php +++ b/module/blog/view/index/index.php @@ -53,8 +53,8 @@ getData(['module',$this->getUrl(0), 'config', 'feeds'])): ?>
- - + ' . $this->getData(['module',$this->getUrl(0), 'config', 'feedsLabel']) . '

' ; ?>
@@ -62,4 +62,4 @@ - \ No newline at end of file + From 7fc128c1fc4558fd7c37cdc07c87cba48c286d7d Mon Sep 17 00:00:00 2001 From: SylvainLelievre Date: Tue, 9 Mar 2021 16:59:32 +0100 Subject: [PATCH 03/12] Correction des dossiers pour inclusion des classes rss --- module/blog/blog.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/blog/blog.php b/module/blog/blog.php index 560086b3..ce001ab8 100755 --- a/module/blog/blog.php +++ b/module/blog/blog.php @@ -99,10 +99,10 @@ class blog extends common { */ public function rss() { // Inclure les classes - include_once 'module/news/vendor/FeedWriter/Item.php'; - include_once 'module/news/vendor/FeedWriter/Feed.php'; - include_once 'module/news/vendor/FeedWriter/RSS2.php'; - include_once 'module/news/vendor/FeedWriter/InvalidOperationException.php'; + include_once 'module/blog/vendor/FeedWriter/Item.php'; + include_once 'module/blog/vendor/FeedWriter/Feed.php'; + include_once 'module/blog/vendor/FeedWriter/RSS2.php'; + include_once 'module/blog/vendor/FeedWriter/InvalidOperationException.php'; date_default_timezone_set('UTC'); $feeds = new \FeedWriter\RSS2(); From 28c5c67e26ce1d6347718121bbb601255f1f4aa8 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Wed, 10 Mar 2021 13:37:13 +0100 Subject: [PATCH 04/12] geturlcontent ajout de curl --- core/class/helper.class.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/class/helper.class.php b/core/class/helper.class.php index 503ea941..2f505797 100755 --- a/core/class/helper.class.php +++ b/core/class/helper.class.php @@ -40,7 +40,7 @@ class helper { } /** - * Fonction pour récupérer le numéro de version en ligne + * Fonction pour récupérer le numéro de version en ligne et le catalogue des modules * @param string $url à récupérer * @return mixed données récupérées */ @@ -58,6 +58,13 @@ class helper { ini_get('allow_url_fopen')){ $handle = fopen ($url, "r"); $url_get_contents_data = stream_get_contents($handle); + }elseif(function_exists('curl_version')){ + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $url); + $url_get_contents_data = curl_exec($ch); + curl_close($ch); }else{ $url_get_contents_data = false; } From 61a3dc6093b8cbeba8c1de401874ddd6fd1459b4 Mon Sep 17 00:00:00 2001 From: fredtempez Date: Wed, 10 Mar 2021 14:48:54 +0100 Subject: [PATCH 05/12] Reverse Sitemap Version --- CHANGES.md | 6 + README.md | 2 +- core/class/SitemapGenerator.class.php | 540 ++++++++++++++ core/class/autoload.php | 4 +- core/class/helper.class.php | 9 +- core/class/sitemap/FileSystem.class.php | 36 - core/class/sitemap/Runtime.class.php | 36 - core/class/sitemap/SitemapGenerator.class.php | 705 ------------------ core/core.php | 36 +- 9 files changed, 572 insertions(+), 802 deletions(-) create mode 100755 core/class/SitemapGenerator.class.php delete mode 100755 core/class/sitemap/FileSystem.class.php delete mode 100755 core/class/sitemap/Runtime.class.php delete mode 100755 core/class/sitemap/SitemapGenerator.class.php diff --git a/CHANGES.md b/CHANGES.md index 5de31615..eacf1472 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Changelog +## version 10.4.06 +- Mise à jour : + - Annulation de la mise à jour SiteMapGenerator 4.3.1 et réinstallation de la version initiale. +- Modification : + - Méthode Curl pour la lecture de données par Url. + ## version 10.4.05 - Mise à jour : - SiteMapGenerator 4.3.1 diff --git a/README.md b/README.md index 54fc703b..73db9e0a 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# ZwiiCMS 10.4.05 +# ZwiiCMS 10.4.06 Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation. diff --git a/core/class/SitemapGenerator.class.php b/core/class/SitemapGenerator.class.php new file mode 100755 index 00000000..f15350d0 --- /dev/null +++ b/core/class/SitemapGenerator.class.php @@ -0,0 +1,540 @@ +urls = new \SplFixedArray(); + $this->baseURL = $baseURL; + $this->basePath = $basePath; + $this->document = new \DOMDocument("1.0"); + $this->document->preserveWhiteSpace = false; + $this->document->formatOutput = true; + } + + /** + * Use this to add many URL at one time. + * Each inside array can have 1 to 4 fields. + * @param $urlsArray + * @throws \InvalidArgumentException + */ + public function addUrls($urlsArray) + { + if (!is_array($urlsArray)) { + throw new \InvalidArgumentException("Array as argument should be given."); + } + foreach ($urlsArray as $url) { + $this->addUrl( + isset($url[0]) ? $url[0] : null, + isset($url[1]) ? $url[1] : null, + isset($url[2]) ? $url[2] : null, + isset($url[3]) ? $url[3] : null + ); + } + } + + /** + * Use this to add single URL to sitemap. + * @param string $url URL + * @param \DateTime $lastModified When it was modified, use ISO 8601 + * @param string $changeFrequency How often search engines should revisit this URL + * @param string $priority Priority of URL on You site + * @see http://en.wikipedia.org/wiki/ISO_8601 + * @see http://php.net/manual/en/function.date.php + * @throws \InvalidArgumentException + */ + public function addUrl($url, \DateTime $lastModified = null, $changeFrequency = null, $priority = null) + { + if ($url == null) { + throw new \InvalidArgumentException("URL is mandatory. At least one argument should be given."); + } + $urlLength = extension_loaded('mbstring') ? mb_strlen($url) : strlen($url); + if ($urlLength > 2048) { + throw new \InvalidArgumentException( + "URL length can't be bigger than 2048 characters. + Note, that precise url length check is guaranteed only using mb_string extension. + Make sure Your server allow to use mbstring extension." + ); + } + $tmp = new \SplFixedArray(1); + + $tmp[self::URL_PARAM_LOC] = $url; + + if (isset($lastModified)) { + $tmp->setSize(2); + $tmp[self::URL_PARAM_LASTMOD] = $lastModified->format(\DateTime::ATOM); + } + + if (isset($changeFrequency)) { + $tmp->setSize(3); + $tmp[self::URL_PARAM_CHANGEFREQ] = $changeFrequency; + } + + if (isset($priority)) { + $tmp->setSize(4); + $tmp[self::URL_PARAM_PRIORITY] = $priority; + } + + if ($this->urls->getSize() === 0) { + $this->urls->setSize(1); + } else { + if ($this->urls->getSize() === $this->urls->key()) { + $this->urls->setSize($this->urls->getSize() * 2); + } + } + + $this->urls[$this->urls->key()] = $tmp; + $this->urls->next(); + } + + + /** + * @throws \BadMethodCallException + * @throws \InvalidArgumentException + * @throws \LengthException + */ + public function createSitemap() + { + if (!isset($this->urls)) { + throw new \BadMethodCallException("To create sitemap, call addUrl or addUrls function first."); + } + if ($this->maxURLsPerSitemap > self::MAX_URLS_PER_SITEMAP) { + throw new \InvalidArgumentException( + "More than " . self::MAX_URLS_PER_SITEMAP . " URLs per single sitemap is not allowed." + ); + } + $generatorInfo = ''; + + + $sitemapHeader = '' . $generatorInfo . ' + + '; + + $sitemapIndexHeader = '' . $generatorInfo . ' + + '; + + + $nullUrls = 0; + foreach ($this->urls as $url) { + if (is_null($url)) { + $nullUrls++; + } + } + + $nonEmptyUrls = $this->urls->getSize() - $nullUrls; + + $chunks = ceil($nonEmptyUrls / $this->maxURLsPerSitemap); + + for ($chunkCounter = 0; $chunkCounter < $chunks; $chunkCounter++) { + $xml = new \SimpleXMLElement($sitemapHeader); + for ($urlCounter = $chunkCounter * $this->maxURLsPerSitemap; + $urlCounter < ($chunkCounter + 1) * $this->maxURLsPerSitemap && $urlCounter < $nonEmptyUrls; + $urlCounter++ + ) { + $row = $xml->addChild('url'); + + $row->addChild( + 'loc', + htmlspecialchars($this->baseURL . $this->urls[$urlCounter][self::URL_PARAM_LOC], ENT_QUOTES, 'UTF-8') + ); + + if ($this->urls[$urlCounter]->getSize() > 1) { + $row->addChild('lastmod', $this->urls[$urlCounter][self::URL_PARAM_LASTMOD]); + } + if ($this->urls[$urlCounter]->getSize() > 2) { + $row->addChild('changefreq', $this->urls[$urlCounter][self::URL_PARAM_CHANGEFREQ]); + } + if ($this->urls[$urlCounter]->getSize() > 3) { + $row->addChild('priority', $this->urls[$urlCounter][self::URL_PARAM_PRIORITY]); + } + } + if (strlen($xml->asXML()) > self::MAX_FILE_SIZE) { + throw new \LengthException( + "Sitemap size equals to " . strlen($xml->asXML()) + . " bytes is more than 10MB (" . self::MAX_FILE_SIZE . " bytes), + please decrease maxURLsPerSitemap variable." + ); + } + $this->sitemaps[] = $xml->asXML(); + } + if (count($this->sitemaps) > $this->maxSitemaps) { + throw new \LengthException( + "Sitemap index can contain {$this->maxSitemaps} sitemaps. + Perhaps You trying to submit too many maps." + ); + } + if (count($this->sitemaps) > 1) { + for ($i = 0; $i < count($this->sitemaps); $i++) { + $this->sitemaps[$i] = array( + str_replace(".xml", ($i + 1) . ".xml", $this->sitemapFileName), + $this->sitemaps[$i] + ); + } + $xml = new \SimpleXMLElement($sitemapIndexHeader); + foreach ($this->sitemaps as $sitemap) { + $row = $xml->addChild('sitemap'); + $row->addChild('loc', $this->baseURL . "/" . $this->getSitemapFileName(htmlentities($sitemap[0]))); + $row->addChild('lastmod', date('c')); + } + $this->sitemapFullURL = $this->baseURL . "/" . $this->sitemapIndexFileName; + $this->sitemapIndex = array( + $this->sitemapIndexFileName, + $xml->asXML() + ); + } else { + $this->sitemapFullURL = $this->baseURL . "/" . $this->getSitemapFileName(); + + $this->sitemaps[0] = array( + $this->sitemapFileName, + $this->sitemaps[0] + ); + } + } + + + /** + * Returns created sitemaps as array of strings. + * Use it You want to work with sitemap without saving it as files. + * @return array of strings + * @access public + */ + public function toArray() + { + if (isset($this->sitemapIndex)) { + return array_merge(array($this->sitemapIndex), $this->sitemaps); + } else { + return $this->sitemaps; + } + } + + /** + * Will write sitemaps as files. + * @access public + * @throws \BadMethodCallException + */ + public function writeSitemap() + { + if (!isset($this->sitemaps)) { + throw new \BadMethodCallException("To write sitemap, call createSitemap function first."); + } + if (isset($this->sitemapIndex)) { + $this->document->loadXML($this->sitemapIndex[1]); + $this->writeFile($this->document->saveXML(), $this->basePath, $this->sitemapIndex[0], true); + foreach ($this->sitemaps as $sitemap) { + $this->writeFile($sitemap[1], $this->basePath, $sitemap[0]); + } + } else { + $this->document->loadXML($this->sitemaps[0][1]); + $this->writeFile($this->document->saveXML(), $this->basePath, $this->sitemaps[0][0], true); + $this->writeFile($this->sitemaps[0][1], $this->basePath, $this->sitemaps[0][0]); + } + } + + + private function getSitemapFileName($name = null) + { + if (!$name) { + $name = $this->sitemapFileName; + } + if ($this->createGZipFile) { + $name .= ".gz"; + } + return $name; + } + + /** + * Save file. + * @param string $content + * @param string $filePath + * @param string $fileName + * @param bool $noGzip + * @return bool + * @access private + */ + private function writeFile($content, $filePath, $fileName, $noGzip = false) + { + if (!$noGzip && $this->createGZipFile) { + return $this->writeGZipFile($content, $filePath, $fileName); + } + $file = fopen($filePath . $fileName, 'w'); + fwrite($file, $content); + return fclose($file); + } + + /** + * Save GZipped file. + * @param string $content + * @param string $filePath + * @param string $fileName + * @return bool + * @access private + */ + private function writeGZipFile($content, $filePath, $fileName) + { + $fileName .= '.gz'; + $file = gzopen($filePath . $fileName, 'w'); + gzwrite($file, $content); + return gzclose($file); + } + + /** + * If robots.txt file exist, will update information about newly created sitemaps. + * If there is no robots.txt will, create one and put into it information about sitemaps. + * @access public + * @throws \BadMethodCallException + */ + public function updateRobots() + { + if (!isset($this->sitemaps)) { + throw new \BadMethodCallException("To update robots.txt, call createSitemap function first."); + } + $sampleRobotsFile = "User-agent: *\nAllow: /"; + if (file_exists($this->basePath . $this->robotsFileName)) { + $robotsFile = explode("\n", file_get_contents($this->basePath . $this->robotsFileName)); + $robotsFileContent = ""; + foreach ($robotsFile as $key => $value) { + if (substr($value, 0, 8) == 'Sitemap:') { + unset($robotsFile[$key]); + } else { + $robotsFileContent .= $value . "\n"; + } + } + $robotsFileContent .= "Sitemap: $this->sitemapFullURL"; + if (!isset($this->sitemapIndex)) { + $robotsFileContent .= "\nSitemap: " . $this->getSitemapFileName($this->sitemapFullURL); + } + file_put_contents($this->basePath . $this->robotsFileName, $robotsFileContent); + } else { + $sampleRobotsFile = $sampleRobotsFile . "\n\nSitemap: " . $this->sitemapFullURL; + if (!isset($this->sitemapIndex)) { + $sampleRobotsFile .= "\nSitemap: " . $this->getSitemapFileName($this->sitemapFullURL); + } + file_put_contents($this->basePath . $this->robotsFileName, $sampleRobotsFile); + } + } + + /** + * Will inform search engines about newly created sitemaps. + * Google, Ask, Bing and Yahoo will be noticed. + * If You don't pass yahooAppId, Yahoo still will be informed, + * but this method can be used once per day. If You will do this often, + * message that limit was exceeded will be returned from Yahoo. + * @param string $yahooAppId Your site Yahoo appid. + * @return array of messages and http codes from each search engine + * @access public + * @throws \BadMethodCallException + */ + public function submitSitemap($yahooAppId = null) + { + if (!isset($this->sitemaps)) { + throw new \BadMethodCallException("To submit sitemap, call createSitemap function first."); + } + if (!extension_loaded('curl')) { + throw new \BadMethodCallException("cURL library is needed to do submission."); + } + $searchEngines = $this->searchEngines; + $searchEngines[0] = isset($yahooAppId) ? + str_replace("USERID", $yahooAppId, $searchEngines[0][0]) : + $searchEngines[0][1]; + $result = array(); + for ($i = 0; $i < count($searchEngines); $i++) { + $submitSite = curl_init($searchEngines[$i] . htmlspecialchars($this->sitemapFullURL, ENT_QUOTES, 'UTF-8')); + curl_setopt($submitSite, CURLOPT_RETURNTRANSFER, true); + $responseContent = curl_exec($submitSite); + $response = curl_getinfo($submitSite); + $submitSiteShort = array_reverse(explode(".", parse_url($searchEngines[$i], PHP_URL_HOST))); + $result[] = array( + "site" => $submitSiteShort[1] . "." . $submitSiteShort[0], + "fullsite" => $searchEngines[$i] . htmlspecialchars($this->sitemapFullURL, ENT_QUOTES, 'UTF-8'), + "http_code" => $response['http_code'], + "message" => str_replace("\n", " ", strip_tags($responseContent)) + ); + } + return $result; + } + + + /** + * Returns array of URLs + * + * Converts internal SplFixedArray to array + * @return array + */ + public function getUrls() + { + $urls = $this->urls->toArray(); + + /** + * @var int $key + * @var \SplFixedArray $urlSplArr + */ + foreach ($urls as $key => $urlSplArr) { + if (!is_null($urlSplArr)) { + $urlArr = $urlSplArr->toArray(); + $url = []; + foreach ($urlArr as $paramIndex => $paramValue) { + switch ($paramIndex) { + case static::URL_PARAM_LOC: + $url['loc'] = $paramValue; + break; + case static::URL_PARAM_CHANGEFREQ: + $url['changefreq'] = $paramValue; + break; + case static::URL_PARAM_LASTMOD: + $url['lastmod'] = $paramValue; + break; + case static::URL_PARAM_PRIORITY: + $url['priority'] = $paramValue; + break; + default: + break; + } + } + $urls[$key] = $url; + } + } + + return $urls; + } + + public function countUrls() + { + return $this->urls->getSize(); + } +} diff --git a/core/class/autoload.php b/core/class/autoload.php index ac507c05..a9d16ed4 100755 --- a/core/class/autoload.php +++ b/core/class/autoload.php @@ -4,9 +4,7 @@ class autoload { public static function autoloader () { require_once 'core/class/helper.class.php'; require_once 'core/class/template.class.php'; - require_once 'core/class/sitemap/Runtime.class.php'; - require_once 'core/class/sitemap/FileSystem.class.php'; - require_once 'core/class/sitemap/SitemapGenerator.class.php'; + require_once 'core/class/SitemapGenerator.class.php'; require_once 'core/class/phpmailer/PHPMailer.class.php'; require_once 'core/class/phpmailer/Exception.class.php'; require_once 'core/class/phpmailer/SMTP.class.php'; diff --git a/core/class/helper.class.php b/core/class/helper.class.php index 396208ec..7c05699a 100755 --- a/core/class/helper.class.php +++ b/core/class/helper.class.php @@ -19,7 +19,7 @@ class helper { - /** + /** * Récupérer l'adresse IP sans tenit compte du proxy * @return string IP adress * Cette focntion est utilisé par user @@ -57,6 +57,13 @@ class helper { ini_get('allow_url_fopen')){ $handle = fopen ($url, "r"); $url_get_contents_data = stream_get_contents($handle); + }elseif(function_exists('curl_version')){ + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $url); + $url_get_contents_data = curl_exec($ch); + curl_close($ch); }else{ $url_get_contents_data = false; } diff --git a/core/class/sitemap/FileSystem.class.php b/core/class/sitemap/FileSystem.class.php deleted file mode 100755 index 261102c6..00000000 --- a/core/class/sitemap/FileSystem.class.php +++ /dev/null @@ -1,36 +0,0 @@ -\n") - private $sitemapUrlCount = 0; - private $generatedFiles = []; - - /** - * @param string $baseURL You site URL - * @param string $basePath Relative path where sitemap and robots should be stored. - * @param FileSystem|null $fs - * @param Runtime|null $runtime - */ - public function __construct(string $baseURL, string $basePath = "", FileSystem $fs = null, Runtime $runtime = null) - { - $this->urls = []; - $this->baseURL = rtrim($baseURL, '/'); - - if ($fs === null) { - $this->fs = new FileSystem(); - } else { - $this->fs = $fs; - } - - if ($runtime === null) { - $this->runtime = new Runtime(); - } else { - $this->runtime = $runtime; - } - - if ($this->runtime->is_writable($basePath) === false) { - throw new InvalidArgumentException( - sprintf('the provided basePath (%s) should be a writable directory,', $basePath) . - ' please check its existence and permissions' - ); - } - if (strlen($basePath) > 0 && substr($basePath, -1) != DIRECTORY_SEPARATOR) { - $basePath = $basePath . DIRECTORY_SEPARATOR; - } - $this->basePath = $basePath; - - $this->xmlWriter = $this->createXmlWriter(); - $this->flushedSitemapFilenameFormat = sprintf("sm-%%d-%d.xml", time()); - } - - private function createXmlWriter(): XMLWriter - { - $w = new XMLWriter(); - $w->openMemory(); - $w->setIndent(true); - return $w; - } - - /** - * @param string $filename - * @return SitemapGenerator - */ - public function setSitemapFilename(string $filename = ''): SitemapGenerator - { - if (strlen($filename) === 0) { - throw new InvalidArgumentException('sitemap filename should not be empty'); - } - if (pathinfo($filename, PATHINFO_EXTENSION) !== 'xml') { - throw new InvalidArgumentException('sitemap filename should have *.xml extension'); - } - $this->sitemapFileName = $filename; - return $this; - } - - /** - * @param string $filename - * @return $this - */ - public function setSitemapIndexFilename(string $filename = ''): SitemapGenerator - { - if (strlen($filename) === 0) { - throw new InvalidArgumentException('filename should not be empty'); - } - $this->sitemapIndexFileName = $filename; - return $this; - } - - /** - * @param string $filename - * @return $this - */ - public function setRobotsFileName(string $filename): SitemapGenerator - { - if (strlen($filename) === 0) { - throw new InvalidArgumentException('filename should not be empty'); - } - $this->robotsFileName = $filename; - return $this; - } - - /** - * @param int $value - * @return $this - */ - public function setMaxUrlsPerSitemap(int $value): SitemapGenerator - { - if ($value < 1 || self::MAX_URLS_PER_SITEMAP < $value) { - throw new OutOfRangeException( - sprintf('value %d is out of range 1-%d', $value, self::MAX_URLS_PER_SITEMAP) - ); - } - $this->maxUrlsPerSitemap = $value; - return $this; - } - - public function enableCompression(): SitemapGenerator - { - $this->isCompressionEnabled = true; - return $this; - } - - public function disableCompression(): SitemapGenerator - { - $this->isCompressionEnabled = false; - return $this; - } - - public function isCompressionEnabled(): bool - { - return $this->isCompressionEnabled; - } - - public function validate( - string $path, - DateTime $lastModified = null, - string $changeFrequency = null, - float $priority = null, - array $alternates = null, - array $extensions = []) - { - if (!(1 <= mb_strlen($path) && mb_strlen($path) <= self::MAX_URL_LEN)) { - throw new InvalidArgumentException( - sprintf("The urlPath argument length must be between 1 and %d.", self::MAX_URL_LEN) - ); - } - if ($changeFrequency !== null && !in_array($changeFrequency, $this->validChangefreqValues)) { - throw new InvalidArgumentException( - 'The change frequency argument should be one of: %s' . implode(',', $this->validChangefreqValues) - ); - } - if ($priority !== null && !in_array($priority, $this->validPriorities)) { - throw new InvalidArgumentException("Priority argument should be a float number in the range [0.0..1.0]"); - } - if ($extensions !== null && isset($extensions['google_video'])) { - GoogleVideoExtension::validate($this->baseURL . $path, $extensions['google_video']); - } - } - - /** - * Add url components. - * Instead of storing all urls in the memory, the generator will flush sets of added urls - * to the temporary files created on your disk. - * The file format is 'sm-{index}-{timestamp}.xml' - * @param string $path - * @param DateTime|null $lastModified - * @param string|null $changeFrequency - * @param float|null $priority - * @param array|null $alternates - * @param array $extensions - * @return $this - */ - public function addURL( - string $path, - DateTime $lastModified = null, - string $changeFrequency = null, - float $priority = null, - array $alternates = null, - array $extensions = [] - ): SitemapGenerator - { - $this->validate($path, $lastModified, $changeFrequency, $priority, $alternates, $extensions); - - if ($this->totalUrlCount >= self::TOTAL_MAX_URLS) { - throw new OutOfRangeException( - sprintf("Max url limit reached (%d)", self::TOTAL_MAX_URLS) - ); - } - if ($this->isSitemapStarted === false) { - $this->writeSitemapStart(); - } - - $this->writeSitemapUrl($this->baseURL . $path, $lastModified, $changeFrequency, $priority, $alternates, $extensions); - - if ($this->totalUrlCount % 1000 === 0 || $this->sitemapUrlCount >= $this->maxUrlsPerSitemap) { - $this->flushWriter(); - } - - if ($this->sitemapUrlCount === $this->maxUrlsPerSitemap) { - $this->writeSitemapEnd(); - } - - return $this; - } - - private function writeSitemapStart() - { - $this->xmlWriter->startDocument("1.0", "UTF-8"); - $this->xmlWriter->writeComment(sprintf('generator-class="%s"', get_class($this))); - $this->xmlWriter->writeComment(sprintf('generator-version="%s"', $this->classVersion)); - $this->xmlWriter->writeComment(sprintf('generated-on="%s"', date('c'))); - $this->xmlWriter->startElement('urlset'); - $this->xmlWriter->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9'); - $this->xmlWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml'); - $this->xmlWriter->writeAttribute('xmlns:video', 'http://www.google.com/schemas/sitemap-video/1.1'); - $this->xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - $this->xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'); - $this->isSitemapStarted = true; - } - - private function writeSitemapUrl($loc, $lastModified, $changeFrequency, $priority, $alternates, $extensions) - { - $this->xmlWriter->startElement('url'); - $this->xmlWriter->writeElement('loc', htmlspecialchars($loc, ENT_QUOTES)); - - if ($lastModified !== null) { - $this->xmlWriter->writeElement('lastmod', $lastModified->format(DateTime::ATOM)); - } - - if ($changeFrequency !== null) { - $this->xmlWriter->writeElement('changefreq', $changeFrequency); - } - - if ($priority !== null) { - $this->xmlWriter->writeElement('priority', number_format($priority, 1, ".", "")); - } - - if (is_array($alternates) && count($alternates) > 0) { - foreach ($alternates as $alternate) { - if (is_array($alternate) && isset($alternate['hreflang']) && isset($alternate['href'])) { - $this->xmlWriter->startElement('xhtml:link'); - $this->xmlWriter->writeAttribute('rel', 'alternate'); - $this->xmlWriter->writeAttribute('hreflang', $alternate['hreflang']); - $this->xmlWriter->writeAttribute('href', $alternate['href']); - $this->xmlWriter->endElement(); - } - } - } - - foreach ($extensions as $extName => $extFields) { - if ($extName === 'google_video') { - GoogleVideoExtension::writeVideoTag($this->xmlWriter, $loc, $extFields); - } - } - - $this->xmlWriter->endElement(); // url - $this->sitemapUrlCount++; - $this->totalUrlCount++; - } - - private function flushWriter() - { - $targetSitemapFilepath = $this->basePath . sprintf($this->flushedSitemapFilenameFormat, $this->flushedSitemapCounter); - $flushedString = $this->xmlWriter->outputMemory(true); - $flushedStringLen = mb_strlen($flushedString); - - if ($flushedStringLen === 0) { - return; - } - - $this->flushedSitemapSize += $flushedStringLen; - - if ($this->flushedSitemapSize > self::MAX_FILE_SIZE - $this->urlsetClosingTagLen) { - $this->writeSitemapEnd(); - $this->writeSitemapStart(); - } - $this->fs->file_put_contents($targetSitemapFilepath, $flushedString, FILE_APPEND); - } - - private function writeSitemapEnd() - { - $targetSitemapFilepath = $this->basePath . sprintf($this->flushedSitemapFilenameFormat, $this->flushedSitemapCounter); - $this->xmlWriter->endElement(); // urlset - $this->xmlWriter->endDocument(); - $this->fs->file_put_contents($targetSitemapFilepath, $this->xmlWriter->flush(true), FILE_APPEND); - $this->isSitemapStarted = false; - $this->flushedSitemaps[] = $targetSitemapFilepath; - $this->flushedSitemapCounter++; - $this->sitemapUrlCount = 0; - } - - /** - * Flush all stored urls from memory to the disk and close all necessary tags. - */ - public function flush() - { - $this->flushWriter(); - if ($this->isSitemapStarted) { - $this->writeSitemapEnd(); - } - } - - /** - * Move flushed files to their final location. Compress if necessary. - */ - public function finalize() - { - $this->generatedFiles = []; - - if (count($this->flushedSitemaps) === 1) { - $targetSitemapFilename = $this->sitemapFileName; - if ($this->isCompressionEnabled) { - $targetSitemapFilename .= '.gz'; - } - - $targetSitemapFilepath = $this->basePath . $targetSitemapFilename; - - if ($this->isCompressionEnabled) { - $this->fs->copy($this->flushedSitemaps[0], 'compress.zlib://' . $targetSitemapFilepath); - $this->fs->unlink($this->flushedSitemaps[0]); - } else { - $this->fs->rename($this->flushedSitemaps[0], $targetSitemapFilepath); - } - $this->generatedFiles['sitemaps_location'] = [$targetSitemapFilepath]; - $this->generatedFiles['sitemaps_index_url'] = $this->baseURL . '/' . $targetSitemapFilename; - } else if (count($this->flushedSitemaps) > 1) { - $ext = '.' . pathinfo($this->sitemapFileName, PATHINFO_EXTENSION); - $targetExt = $ext; - if ($this->isCompressionEnabled) { - $targetExt .= '.gz'; - } - - $sitemapsUrls = []; - $targetSitemapFilepaths = []; - foreach ($this->flushedSitemaps as $i => $flushedSitemap) { - $targetSitemapFilename = str_replace($ext, ($i + 1) . $targetExt, $this->sitemapFileName); - $targetSitemapFilepath = $this->basePath . $targetSitemapFilename; - - if ($this->isCompressionEnabled) { - $this->fs->copy($flushedSitemap, 'compress.zlib://' . $targetSitemapFilepath); - $this->fs->unlink($flushedSitemap); - } else { - $this->fs->rename($flushedSitemap, $targetSitemapFilepath); - } - $sitemapsUrls[] = htmlspecialchars($this->baseURL . '/' . $targetSitemapFilename, ENT_QUOTES); - $targetSitemapFilepaths[] = $targetSitemapFilepath; - } - - $targetSitemapIndexFilepath = $this->basePath . $this->sitemapIndexFileName; - $this->createSitemapIndex($sitemapsUrls, $targetSitemapIndexFilepath); - $this->generatedFiles['sitemaps_location'] = $targetSitemapFilepaths; - $this->generatedFiles['sitemaps_index_location'] = $targetSitemapIndexFilepath; - $this->generatedFiles['sitemaps_index_url'] = $this->baseURL . '/' . $this->sitemapIndexFileName; - } else { - throw new RuntimeException('failed to finalize, please add urls and flush first'); - } - } - - private function createSitemapIndex($sitemapsUrls, $sitemapIndexFileName) - { - $this->xmlWriter->flush(true); - $this->writeSitemapIndexStart(); - foreach ($sitemapsUrls as $sitemapsUrl) { - $this->writeSitemapIndexUrl($sitemapsUrl); - } - $this->writeSitemapIndexEnd(); - $this->fs->file_put_contents( - $sitemapIndexFileName, - $this->xmlWriter->flush(true), - FILE_APPEND - ); - } - - private function writeSitemapIndexStart() - { - $this->xmlWriter->startDocument("1.0", "UTF-8"); - $this->xmlWriter->writeComment(sprintf('generator-class="%s"', get_class($this))); - $this->xmlWriter->writeComment(sprintf('generator-version="%s"', $this->classVersion)); - $this->xmlWriter->writeComment(sprintf('generated-on="%s"', date('c'))); - $this->xmlWriter->startElement('sitemapindex'); - $this->xmlWriter->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9'); - $this->xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); - $this->xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'); - } - - private function writeSitemapIndexUrl($url) - { - $this->xmlWriter->startElement('sitemap'); - $this->xmlWriter->writeElement('loc', htmlspecialchars($url, ENT_QUOTES)); - $this->xmlWriter->writeElement('lastmod', date('c')); - $this->xmlWriter->endElement(); // sitemap - } - - private function writeSitemapIndexEnd() - { - $this->xmlWriter->endElement(); // sitemapindex - $this->xmlWriter->endDocument(); - } - - /** - * @return array Array of previously generated files - */ - public function getGeneratedFiles(): array - { - return $this->generatedFiles; - } - - /** - * Will inform search engines about newly created sitemaps. - * Google, Ask, Bing and Yahoo will be noticed. - * If You don't pass yahooAppId, Yahoo still will be informed, - * but this method can be used once per day. If You will do this often, - * message that limit was exceeded will be returned from Yahoo. - * @param string $yahooAppId Your site Yahoo appid. - * @return array of messages and http codes from each search engine - * @access public - * @throws BadMethodCallException - */ - public function submitSitemap($yahooAppId = null): array - { - if (count($this->generatedFiles) === 0) { - throw new BadMethodCallException("To update robots.txt, call finalize() first."); - } - if (!$this->runtime->extension_loaded('curl')) { - throw new BadMethodCallException("cURL extension is needed to do submission."); - } - $searchEngines = $this->searchEngines; - $searchEngines[0] = isset($yahooAppId) ? - str_replace("USERID", $yahooAppId, $searchEngines[0][0]) : - $searchEngines[0][1]; - $result = []; - for ($i = 0; $i < count($searchEngines); $i++) { - $submitUrl = $searchEngines[$i] . htmlspecialchars($this->generatedFiles['sitemaps_index_url'], ENT_QUOTES); - $submitSite = $this->runtime->curl_init($submitUrl); - $this->runtime->curl_setopt($submitSite, CURLOPT_RETURNTRANSFER, true); - $responseContent = $this->runtime->curl_exec($submitSite); - $response = $this->runtime->curl_getinfo($submitSite); - $submitSiteShort = array_reverse(explode(".", parse_url($searchEngines[$i], PHP_URL_HOST))); - $result[] = [ - "site" => $submitSiteShort[1] . "." . $submitSiteShort[0], - "fullsite" => $submitUrl, - "http_code" => $response['http_code'], - "message" => str_replace("\n", " ", strip_tags($responseContent)), - ]; - } - return $result; - } - - /** - * Adds sitemap url to robots.txt file located in basePath. - * If robots.txt file exists, - * the function will append sitemap url to file. - * If robots.txt does not exist, - * the function will create new robots.txt file with sample content and sitemap url. - * @access public - * @throws BadMethodCallException - * @throws RuntimeException - */ - public function updateRobots(): SitemapGenerator - { - if (count($this->generatedFiles) === 0) { - throw new BadMethodCallException("To update robots.txt, call finalize() first."); - } - - $robotsFilePath = $this->basePath . $this->robotsFileName; - - $robotsFileContent = $this->createNewRobotsContentFromFile($robotsFilePath); - - $this->fs->file_put_contents($robotsFilePath, $robotsFileContent); - - return $this; - } - - /** - * @param $filepath - * @return string - */ - private function createNewRobotsContentFromFile($filepath): string - { - if ($this->fs->file_exists($filepath)) { - $robotsFileContent = ""; - $robotsFile = explode(PHP_EOL, $this->fs->file_get_contents($filepath)); - foreach ($robotsFile as $key => $value) { - if (substr($value, 0, 8) == 'Sitemap:') { - unset($robotsFile[$key]); - } else { - $robotsFileContent .= $value . PHP_EOL; - } - } - } else { - $robotsFileContent = $this->getSampleRobotsContent(); - } - - $robotsFileContent .= "Sitemap: {$this->generatedFiles['sitemaps_index_url']}"; - - return $robotsFileContent; - } - - /** - * @return string - * @access private - */ - private function getSampleRobotsContent(): string - { - return implode(PHP_EOL, $this->sampleRobotsLines) . PHP_EOL; - } -} diff --git a/core/core.php b/core/core.php index d2fa5506..4dd16063 100755 --- a/core/core.php +++ b/core/core.php @@ -740,26 +740,22 @@ class common { $timezone = $this->getData(['config','timezone']); - $outputDir = getcwd(); - - $sitemap = new \Icamys\SitemapGenerator\SitemapGenerator(helper::baseurl(false),$outputDir); + $sitemap = new \Icamys\SitemapGenerator\SitemapGenerator(helper::baseurl()); // will create also compressed (gzipped) sitemap - $sitemap->enableCompression(); + $sitemap->createGZipFile = true; // determine how many urls should be put into one file // according to standard protocol 50000 is maximum value (see http://www.sitemaps.org/protocol.html) - $sitemap->setMaxUrlsPerSitemap(50000); + $sitemap->maxURLsPerSitemap = 50000; // sitemap file name - $sitemap->setSitemapFileName("sitemap.xml"); - - // Set the sitemap index file name - $sitemap->setSitemapIndexFileName("sitemap-index.xml"); + $sitemap->sitemapFileName = "sitemap.xml"; $datetime = new DateTime(date('c')); $datetime->format(DateTime::ATOM); // Updated ISO8601 - + // sitemap index file name + $sitemap->sitemapIndexFileName = "sitemap-index.xml"; foreach($this->getHierarchy(null, null, null) as $parentPageId => $childrenPageIds) { // Exclure les barres et les pages non publiques et les pages masquées if ($this->getData(['page',$parentPageId,'group']) !== 0 || @@ -801,22 +797,17 @@ class common { } - // Flush all stored urls from memory to the disk and close all necessary tags. - $sitemap->flush(); + // generating internally a sitemap + $sitemap->createSitemap(); - // Move flushed files to their final location. Compress if the option is enabled. - $sitemap->finalize(); - - // Update robots.txt file in output directory or create a new one - $sitemap->updateRobots(); - - // Submit your sitemaps to Google, Yahoo, Bing and Ask.com - $sitemap->submitSitemap(); + // writing early generated sitemap to file + $sitemap->writeSitemap(); return(file_exists('sitemap.xml')); } + /* * Création d'une miniature * Fonction utilisée lors de la mise à jour d'une version 9 à une version 10 @@ -1578,6 +1569,11 @@ class common { if ($this->getData(['core', 'dataVersion']) < 10405) { $this->setData(['core', 'dataVersion', 10405]); } + // Version 10.4.06 + if ($this->getData(['core', 'dataVersion']) < 10406) { + $this->removeDir ('core/class/sitemap'); + $this->setData(['core', 'dataVersion', 10406]); + } } } From 0d157b8957013a755c17638677cfedd395d1fcf4 Mon Sep 17 00:00:00 2001 From: fredtempez Date: Wed, 10 Mar 2021 18:52:17 +0100 Subject: [PATCH 06/12] Revert "Merge branch '10406' into 10500" This reverts commit f7d2c36086ca01f54ec95c55a744f96e665ac5a7, reversing changes made to 60bb775109578bf05e9689c8452d7b4afaa33347. --- core/class/SitemapGenerator.class.php | 540 -------------- core/class/autoload.php | 4 +- core/class/helper.class.php | 2 +- core/class/sitemap/FileSystem.class.php | 36 + core/class/sitemap/Runtime.class.php | 36 + core/class/sitemap/SitemapGenerator.class.php | 705 ++++++++++++++++++ core/core.php | 36 +- 7 files changed, 801 insertions(+), 558 deletions(-) delete mode 100755 core/class/SitemapGenerator.class.php create mode 100755 core/class/sitemap/FileSystem.class.php create mode 100755 core/class/sitemap/Runtime.class.php create mode 100755 core/class/sitemap/SitemapGenerator.class.php diff --git a/core/class/SitemapGenerator.class.php b/core/class/SitemapGenerator.class.php deleted file mode 100755 index f15350d0..00000000 --- a/core/class/SitemapGenerator.class.php +++ /dev/null @@ -1,540 +0,0 @@ -urls = new \SplFixedArray(); - $this->baseURL = $baseURL; - $this->basePath = $basePath; - $this->document = new \DOMDocument("1.0"); - $this->document->preserveWhiteSpace = false; - $this->document->formatOutput = true; - } - - /** - * Use this to add many URL at one time. - * Each inside array can have 1 to 4 fields. - * @param $urlsArray - * @throws \InvalidArgumentException - */ - public function addUrls($urlsArray) - { - if (!is_array($urlsArray)) { - throw new \InvalidArgumentException("Array as argument should be given."); - } - foreach ($urlsArray as $url) { - $this->addUrl( - isset($url[0]) ? $url[0] : null, - isset($url[1]) ? $url[1] : null, - isset($url[2]) ? $url[2] : null, - isset($url[3]) ? $url[3] : null - ); - } - } - - /** - * Use this to add single URL to sitemap. - * @param string $url URL - * @param \DateTime $lastModified When it was modified, use ISO 8601 - * @param string $changeFrequency How often search engines should revisit this URL - * @param string $priority Priority of URL on You site - * @see http://en.wikipedia.org/wiki/ISO_8601 - * @see http://php.net/manual/en/function.date.php - * @throws \InvalidArgumentException - */ - public function addUrl($url, \DateTime $lastModified = null, $changeFrequency = null, $priority = null) - { - if ($url == null) { - throw new \InvalidArgumentException("URL is mandatory. At least one argument should be given."); - } - $urlLength = extension_loaded('mbstring') ? mb_strlen($url) : strlen($url); - if ($urlLength > 2048) { - throw new \InvalidArgumentException( - "URL length can't be bigger than 2048 characters. - Note, that precise url length check is guaranteed only using mb_string extension. - Make sure Your server allow to use mbstring extension." - ); - } - $tmp = new \SplFixedArray(1); - - $tmp[self::URL_PARAM_LOC] = $url; - - if (isset($lastModified)) { - $tmp->setSize(2); - $tmp[self::URL_PARAM_LASTMOD] = $lastModified->format(\DateTime::ATOM); - } - - if (isset($changeFrequency)) { - $tmp->setSize(3); - $tmp[self::URL_PARAM_CHANGEFREQ] = $changeFrequency; - } - - if (isset($priority)) { - $tmp->setSize(4); - $tmp[self::URL_PARAM_PRIORITY] = $priority; - } - - if ($this->urls->getSize() === 0) { - $this->urls->setSize(1); - } else { - if ($this->urls->getSize() === $this->urls->key()) { - $this->urls->setSize($this->urls->getSize() * 2); - } - } - - $this->urls[$this->urls->key()] = $tmp; - $this->urls->next(); - } - - - /** - * @throws \BadMethodCallException - * @throws \InvalidArgumentException - * @throws \LengthException - */ - public function createSitemap() - { - if (!isset($this->urls)) { - throw new \BadMethodCallException("To create sitemap, call addUrl or addUrls function first."); - } - if ($this->maxURLsPerSitemap > self::MAX_URLS_PER_SITEMAP) { - throw new \InvalidArgumentException( - "More than " . self::MAX_URLS_PER_SITEMAP . " URLs per single sitemap is not allowed." - ); - } - $generatorInfo = ''; - - - $sitemapHeader = '' . $generatorInfo . ' - - '; - - $sitemapIndexHeader = '' . $generatorInfo . ' - - '; - - - $nullUrls = 0; - foreach ($this->urls as $url) { - if (is_null($url)) { - $nullUrls++; - } - } - - $nonEmptyUrls = $this->urls->getSize() - $nullUrls; - - $chunks = ceil($nonEmptyUrls / $this->maxURLsPerSitemap); - - for ($chunkCounter = 0; $chunkCounter < $chunks; $chunkCounter++) { - $xml = new \SimpleXMLElement($sitemapHeader); - for ($urlCounter = $chunkCounter * $this->maxURLsPerSitemap; - $urlCounter < ($chunkCounter + 1) * $this->maxURLsPerSitemap && $urlCounter < $nonEmptyUrls; - $urlCounter++ - ) { - $row = $xml->addChild('url'); - - $row->addChild( - 'loc', - htmlspecialchars($this->baseURL . $this->urls[$urlCounter][self::URL_PARAM_LOC], ENT_QUOTES, 'UTF-8') - ); - - if ($this->urls[$urlCounter]->getSize() > 1) { - $row->addChild('lastmod', $this->urls[$urlCounter][self::URL_PARAM_LASTMOD]); - } - if ($this->urls[$urlCounter]->getSize() > 2) { - $row->addChild('changefreq', $this->urls[$urlCounter][self::URL_PARAM_CHANGEFREQ]); - } - if ($this->urls[$urlCounter]->getSize() > 3) { - $row->addChild('priority', $this->urls[$urlCounter][self::URL_PARAM_PRIORITY]); - } - } - if (strlen($xml->asXML()) > self::MAX_FILE_SIZE) { - throw new \LengthException( - "Sitemap size equals to " . strlen($xml->asXML()) - . " bytes is more than 10MB (" . self::MAX_FILE_SIZE . " bytes), - please decrease maxURLsPerSitemap variable." - ); - } - $this->sitemaps[] = $xml->asXML(); - } - if (count($this->sitemaps) > $this->maxSitemaps) { - throw new \LengthException( - "Sitemap index can contain {$this->maxSitemaps} sitemaps. - Perhaps You trying to submit too many maps." - ); - } - if (count($this->sitemaps) > 1) { - for ($i = 0; $i < count($this->sitemaps); $i++) { - $this->sitemaps[$i] = array( - str_replace(".xml", ($i + 1) . ".xml", $this->sitemapFileName), - $this->sitemaps[$i] - ); - } - $xml = new \SimpleXMLElement($sitemapIndexHeader); - foreach ($this->sitemaps as $sitemap) { - $row = $xml->addChild('sitemap'); - $row->addChild('loc', $this->baseURL . "/" . $this->getSitemapFileName(htmlentities($sitemap[0]))); - $row->addChild('lastmod', date('c')); - } - $this->sitemapFullURL = $this->baseURL . "/" . $this->sitemapIndexFileName; - $this->sitemapIndex = array( - $this->sitemapIndexFileName, - $xml->asXML() - ); - } else { - $this->sitemapFullURL = $this->baseURL . "/" . $this->getSitemapFileName(); - - $this->sitemaps[0] = array( - $this->sitemapFileName, - $this->sitemaps[0] - ); - } - } - - - /** - * Returns created sitemaps as array of strings. - * Use it You want to work with sitemap without saving it as files. - * @return array of strings - * @access public - */ - public function toArray() - { - if (isset($this->sitemapIndex)) { - return array_merge(array($this->sitemapIndex), $this->sitemaps); - } else { - return $this->sitemaps; - } - } - - /** - * Will write sitemaps as files. - * @access public - * @throws \BadMethodCallException - */ - public function writeSitemap() - { - if (!isset($this->sitemaps)) { - throw new \BadMethodCallException("To write sitemap, call createSitemap function first."); - } - if (isset($this->sitemapIndex)) { - $this->document->loadXML($this->sitemapIndex[1]); - $this->writeFile($this->document->saveXML(), $this->basePath, $this->sitemapIndex[0], true); - foreach ($this->sitemaps as $sitemap) { - $this->writeFile($sitemap[1], $this->basePath, $sitemap[0]); - } - } else { - $this->document->loadXML($this->sitemaps[0][1]); - $this->writeFile($this->document->saveXML(), $this->basePath, $this->sitemaps[0][0], true); - $this->writeFile($this->sitemaps[0][1], $this->basePath, $this->sitemaps[0][0]); - } - } - - - private function getSitemapFileName($name = null) - { - if (!$name) { - $name = $this->sitemapFileName; - } - if ($this->createGZipFile) { - $name .= ".gz"; - } - return $name; - } - - /** - * Save file. - * @param string $content - * @param string $filePath - * @param string $fileName - * @param bool $noGzip - * @return bool - * @access private - */ - private function writeFile($content, $filePath, $fileName, $noGzip = false) - { - if (!$noGzip && $this->createGZipFile) { - return $this->writeGZipFile($content, $filePath, $fileName); - } - $file = fopen($filePath . $fileName, 'w'); - fwrite($file, $content); - return fclose($file); - } - - /** - * Save GZipped file. - * @param string $content - * @param string $filePath - * @param string $fileName - * @return bool - * @access private - */ - private function writeGZipFile($content, $filePath, $fileName) - { - $fileName .= '.gz'; - $file = gzopen($filePath . $fileName, 'w'); - gzwrite($file, $content); - return gzclose($file); - } - - /** - * If robots.txt file exist, will update information about newly created sitemaps. - * If there is no robots.txt will, create one and put into it information about sitemaps. - * @access public - * @throws \BadMethodCallException - */ - public function updateRobots() - { - if (!isset($this->sitemaps)) { - throw new \BadMethodCallException("To update robots.txt, call createSitemap function first."); - } - $sampleRobotsFile = "User-agent: *\nAllow: /"; - if (file_exists($this->basePath . $this->robotsFileName)) { - $robotsFile = explode("\n", file_get_contents($this->basePath . $this->robotsFileName)); - $robotsFileContent = ""; - foreach ($robotsFile as $key => $value) { - if (substr($value, 0, 8) == 'Sitemap:') { - unset($robotsFile[$key]); - } else { - $robotsFileContent .= $value . "\n"; - } - } - $robotsFileContent .= "Sitemap: $this->sitemapFullURL"; - if (!isset($this->sitemapIndex)) { - $robotsFileContent .= "\nSitemap: " . $this->getSitemapFileName($this->sitemapFullURL); - } - file_put_contents($this->basePath . $this->robotsFileName, $robotsFileContent); - } else { - $sampleRobotsFile = $sampleRobotsFile . "\n\nSitemap: " . $this->sitemapFullURL; - if (!isset($this->sitemapIndex)) { - $sampleRobotsFile .= "\nSitemap: " . $this->getSitemapFileName($this->sitemapFullURL); - } - file_put_contents($this->basePath . $this->robotsFileName, $sampleRobotsFile); - } - } - - /** - * Will inform search engines about newly created sitemaps. - * Google, Ask, Bing and Yahoo will be noticed. - * If You don't pass yahooAppId, Yahoo still will be informed, - * but this method can be used once per day. If You will do this often, - * message that limit was exceeded will be returned from Yahoo. - * @param string $yahooAppId Your site Yahoo appid. - * @return array of messages and http codes from each search engine - * @access public - * @throws \BadMethodCallException - */ - public function submitSitemap($yahooAppId = null) - { - if (!isset($this->sitemaps)) { - throw new \BadMethodCallException("To submit sitemap, call createSitemap function first."); - } - if (!extension_loaded('curl')) { - throw new \BadMethodCallException("cURL library is needed to do submission."); - } - $searchEngines = $this->searchEngines; - $searchEngines[0] = isset($yahooAppId) ? - str_replace("USERID", $yahooAppId, $searchEngines[0][0]) : - $searchEngines[0][1]; - $result = array(); - for ($i = 0; $i < count($searchEngines); $i++) { - $submitSite = curl_init($searchEngines[$i] . htmlspecialchars($this->sitemapFullURL, ENT_QUOTES, 'UTF-8')); - curl_setopt($submitSite, CURLOPT_RETURNTRANSFER, true); - $responseContent = curl_exec($submitSite); - $response = curl_getinfo($submitSite); - $submitSiteShort = array_reverse(explode(".", parse_url($searchEngines[$i], PHP_URL_HOST))); - $result[] = array( - "site" => $submitSiteShort[1] . "." . $submitSiteShort[0], - "fullsite" => $searchEngines[$i] . htmlspecialchars($this->sitemapFullURL, ENT_QUOTES, 'UTF-8'), - "http_code" => $response['http_code'], - "message" => str_replace("\n", " ", strip_tags($responseContent)) - ); - } - return $result; - } - - - /** - * Returns array of URLs - * - * Converts internal SplFixedArray to array - * @return array - */ - public function getUrls() - { - $urls = $this->urls->toArray(); - - /** - * @var int $key - * @var \SplFixedArray $urlSplArr - */ - foreach ($urls as $key => $urlSplArr) { - if (!is_null($urlSplArr)) { - $urlArr = $urlSplArr->toArray(); - $url = []; - foreach ($urlArr as $paramIndex => $paramValue) { - switch ($paramIndex) { - case static::URL_PARAM_LOC: - $url['loc'] = $paramValue; - break; - case static::URL_PARAM_CHANGEFREQ: - $url['changefreq'] = $paramValue; - break; - case static::URL_PARAM_LASTMOD: - $url['lastmod'] = $paramValue; - break; - case static::URL_PARAM_PRIORITY: - $url['priority'] = $paramValue; - break; - default: - break; - } - } - $urls[$key] = $url; - } - } - - return $urls; - } - - public function countUrls() - { - return $this->urls->getSize(); - } -} diff --git a/core/class/autoload.php b/core/class/autoload.php index a9d16ed4..ac507c05 100755 --- a/core/class/autoload.php +++ b/core/class/autoload.php @@ -4,7 +4,9 @@ class autoload { public static function autoloader () { require_once 'core/class/helper.class.php'; require_once 'core/class/template.class.php'; - require_once 'core/class/SitemapGenerator.class.php'; + require_once 'core/class/sitemap/Runtime.class.php'; + require_once 'core/class/sitemap/FileSystem.class.php'; + require_once 'core/class/sitemap/SitemapGenerator.class.php'; require_once 'core/class/phpmailer/PHPMailer.class.php'; require_once 'core/class/phpmailer/Exception.class.php'; require_once 'core/class/phpmailer/SMTP.class.php'; diff --git a/core/class/helper.class.php b/core/class/helper.class.php index b0a8ec5f..2f505797 100755 --- a/core/class/helper.class.php +++ b/core/class/helper.class.php @@ -64,7 +64,7 @@ class helper { curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); $url_get_contents_data = curl_exec($ch); - curl_close($ch); + curl_close($ch); }else{ $url_get_contents_data = false; } diff --git a/core/class/sitemap/FileSystem.class.php b/core/class/sitemap/FileSystem.class.php new file mode 100755 index 00000000..261102c6 --- /dev/null +++ b/core/class/sitemap/FileSystem.class.php @@ -0,0 +1,36 @@ +\n") + private $sitemapUrlCount = 0; + private $generatedFiles = []; + + /** + * @param string $baseURL You site URL + * @param string $basePath Relative path where sitemap and robots should be stored. + * @param FileSystem|null $fs + * @param Runtime|null $runtime + */ + public function __construct(string $baseURL, string $basePath = "", FileSystem $fs = null, Runtime $runtime = null) + { + $this->urls = []; + $this->baseURL = rtrim($baseURL, '/'); + + if ($fs === null) { + $this->fs = new FileSystem(); + } else { + $this->fs = $fs; + } + + if ($runtime === null) { + $this->runtime = new Runtime(); + } else { + $this->runtime = $runtime; + } + + if ($this->runtime->is_writable($basePath) === false) { + throw new InvalidArgumentException( + sprintf('the provided basePath (%s) should be a writable directory,', $basePath) . + ' please check its existence and permissions' + ); + } + if (strlen($basePath) > 0 && substr($basePath, -1) != DIRECTORY_SEPARATOR) { + $basePath = $basePath . DIRECTORY_SEPARATOR; + } + $this->basePath = $basePath; + + $this->xmlWriter = $this->createXmlWriter(); + $this->flushedSitemapFilenameFormat = sprintf("sm-%%d-%d.xml", time()); + } + + private function createXmlWriter(): XMLWriter + { + $w = new XMLWriter(); + $w->openMemory(); + $w->setIndent(true); + return $w; + } + + /** + * @param string $filename + * @return SitemapGenerator + */ + public function setSitemapFilename(string $filename = ''): SitemapGenerator + { + if (strlen($filename) === 0) { + throw new InvalidArgumentException('sitemap filename should not be empty'); + } + if (pathinfo($filename, PATHINFO_EXTENSION) !== 'xml') { + throw new InvalidArgumentException('sitemap filename should have *.xml extension'); + } + $this->sitemapFileName = $filename; + return $this; + } + + /** + * @param string $filename + * @return $this + */ + public function setSitemapIndexFilename(string $filename = ''): SitemapGenerator + { + if (strlen($filename) === 0) { + throw new InvalidArgumentException('filename should not be empty'); + } + $this->sitemapIndexFileName = $filename; + return $this; + } + + /** + * @param string $filename + * @return $this + */ + public function setRobotsFileName(string $filename): SitemapGenerator + { + if (strlen($filename) === 0) { + throw new InvalidArgumentException('filename should not be empty'); + } + $this->robotsFileName = $filename; + return $this; + } + + /** + * @param int $value + * @return $this + */ + public function setMaxUrlsPerSitemap(int $value): SitemapGenerator + { + if ($value < 1 || self::MAX_URLS_PER_SITEMAP < $value) { + throw new OutOfRangeException( + sprintf('value %d is out of range 1-%d', $value, self::MAX_URLS_PER_SITEMAP) + ); + } + $this->maxUrlsPerSitemap = $value; + return $this; + } + + public function enableCompression(): SitemapGenerator + { + $this->isCompressionEnabled = true; + return $this; + } + + public function disableCompression(): SitemapGenerator + { + $this->isCompressionEnabled = false; + return $this; + } + + public function isCompressionEnabled(): bool + { + return $this->isCompressionEnabled; + } + + public function validate( + string $path, + DateTime $lastModified = null, + string $changeFrequency = null, + float $priority = null, + array $alternates = null, + array $extensions = []) + { + if (!(1 <= mb_strlen($path) && mb_strlen($path) <= self::MAX_URL_LEN)) { + throw new InvalidArgumentException( + sprintf("The urlPath argument length must be between 1 and %d.", self::MAX_URL_LEN) + ); + } + if ($changeFrequency !== null && !in_array($changeFrequency, $this->validChangefreqValues)) { + throw new InvalidArgumentException( + 'The change frequency argument should be one of: %s' . implode(',', $this->validChangefreqValues) + ); + } + if ($priority !== null && !in_array($priority, $this->validPriorities)) { + throw new InvalidArgumentException("Priority argument should be a float number in the range [0.0..1.0]"); + } + if ($extensions !== null && isset($extensions['google_video'])) { + GoogleVideoExtension::validate($this->baseURL . $path, $extensions['google_video']); + } + } + + /** + * Add url components. + * Instead of storing all urls in the memory, the generator will flush sets of added urls + * to the temporary files created on your disk. + * The file format is 'sm-{index}-{timestamp}.xml' + * @param string $path + * @param DateTime|null $lastModified + * @param string|null $changeFrequency + * @param float|null $priority + * @param array|null $alternates + * @param array $extensions + * @return $this + */ + public function addURL( + string $path, + DateTime $lastModified = null, + string $changeFrequency = null, + float $priority = null, + array $alternates = null, + array $extensions = [] + ): SitemapGenerator + { + $this->validate($path, $lastModified, $changeFrequency, $priority, $alternates, $extensions); + + if ($this->totalUrlCount >= self::TOTAL_MAX_URLS) { + throw new OutOfRangeException( + sprintf("Max url limit reached (%d)", self::TOTAL_MAX_URLS) + ); + } + if ($this->isSitemapStarted === false) { + $this->writeSitemapStart(); + } + + $this->writeSitemapUrl($this->baseURL . $path, $lastModified, $changeFrequency, $priority, $alternates, $extensions); + + if ($this->totalUrlCount % 1000 === 0 || $this->sitemapUrlCount >= $this->maxUrlsPerSitemap) { + $this->flushWriter(); + } + + if ($this->sitemapUrlCount === $this->maxUrlsPerSitemap) { + $this->writeSitemapEnd(); + } + + return $this; + } + + private function writeSitemapStart() + { + $this->xmlWriter->startDocument("1.0", "UTF-8"); + $this->xmlWriter->writeComment(sprintf('generator-class="%s"', get_class($this))); + $this->xmlWriter->writeComment(sprintf('generator-version="%s"', $this->classVersion)); + $this->xmlWriter->writeComment(sprintf('generated-on="%s"', date('c'))); + $this->xmlWriter->startElement('urlset'); + $this->xmlWriter->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9'); + $this->xmlWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml'); + $this->xmlWriter->writeAttribute('xmlns:video', 'http://www.google.com/schemas/sitemap-video/1.1'); + $this->xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $this->xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'); + $this->isSitemapStarted = true; + } + + private function writeSitemapUrl($loc, $lastModified, $changeFrequency, $priority, $alternates, $extensions) + { + $this->xmlWriter->startElement('url'); + $this->xmlWriter->writeElement('loc', htmlspecialchars($loc, ENT_QUOTES)); + + if ($lastModified !== null) { + $this->xmlWriter->writeElement('lastmod', $lastModified->format(DateTime::ATOM)); + } + + if ($changeFrequency !== null) { + $this->xmlWriter->writeElement('changefreq', $changeFrequency); + } + + if ($priority !== null) { + $this->xmlWriter->writeElement('priority', number_format($priority, 1, ".", "")); + } + + if (is_array($alternates) && count($alternates) > 0) { + foreach ($alternates as $alternate) { + if (is_array($alternate) && isset($alternate['hreflang']) && isset($alternate['href'])) { + $this->xmlWriter->startElement('xhtml:link'); + $this->xmlWriter->writeAttribute('rel', 'alternate'); + $this->xmlWriter->writeAttribute('hreflang', $alternate['hreflang']); + $this->xmlWriter->writeAttribute('href', $alternate['href']); + $this->xmlWriter->endElement(); + } + } + } + + foreach ($extensions as $extName => $extFields) { + if ($extName === 'google_video') { + GoogleVideoExtension::writeVideoTag($this->xmlWriter, $loc, $extFields); + } + } + + $this->xmlWriter->endElement(); // url + $this->sitemapUrlCount++; + $this->totalUrlCount++; + } + + private function flushWriter() + { + $targetSitemapFilepath = $this->basePath . sprintf($this->flushedSitemapFilenameFormat, $this->flushedSitemapCounter); + $flushedString = $this->xmlWriter->outputMemory(true); + $flushedStringLen = mb_strlen($flushedString); + + if ($flushedStringLen === 0) { + return; + } + + $this->flushedSitemapSize += $flushedStringLen; + + if ($this->flushedSitemapSize > self::MAX_FILE_SIZE - $this->urlsetClosingTagLen) { + $this->writeSitemapEnd(); + $this->writeSitemapStart(); + } + $this->fs->file_put_contents($targetSitemapFilepath, $flushedString, FILE_APPEND); + } + + private function writeSitemapEnd() + { + $targetSitemapFilepath = $this->basePath . sprintf($this->flushedSitemapFilenameFormat, $this->flushedSitemapCounter); + $this->xmlWriter->endElement(); // urlset + $this->xmlWriter->endDocument(); + $this->fs->file_put_contents($targetSitemapFilepath, $this->xmlWriter->flush(true), FILE_APPEND); + $this->isSitemapStarted = false; + $this->flushedSitemaps[] = $targetSitemapFilepath; + $this->flushedSitemapCounter++; + $this->sitemapUrlCount = 0; + } + + /** + * Flush all stored urls from memory to the disk and close all necessary tags. + */ + public function flush() + { + $this->flushWriter(); + if ($this->isSitemapStarted) { + $this->writeSitemapEnd(); + } + } + + /** + * Move flushed files to their final location. Compress if necessary. + */ + public function finalize() + { + $this->generatedFiles = []; + + if (count($this->flushedSitemaps) === 1) { + $targetSitemapFilename = $this->sitemapFileName; + if ($this->isCompressionEnabled) { + $targetSitemapFilename .= '.gz'; + } + + $targetSitemapFilepath = $this->basePath . $targetSitemapFilename; + + if ($this->isCompressionEnabled) { + $this->fs->copy($this->flushedSitemaps[0], 'compress.zlib://' . $targetSitemapFilepath); + $this->fs->unlink($this->flushedSitemaps[0]); + } else { + $this->fs->rename($this->flushedSitemaps[0], $targetSitemapFilepath); + } + $this->generatedFiles['sitemaps_location'] = [$targetSitemapFilepath]; + $this->generatedFiles['sitemaps_index_url'] = $this->baseURL . '/' . $targetSitemapFilename; + } else if (count($this->flushedSitemaps) > 1) { + $ext = '.' . pathinfo($this->sitemapFileName, PATHINFO_EXTENSION); + $targetExt = $ext; + if ($this->isCompressionEnabled) { + $targetExt .= '.gz'; + } + + $sitemapsUrls = []; + $targetSitemapFilepaths = []; + foreach ($this->flushedSitemaps as $i => $flushedSitemap) { + $targetSitemapFilename = str_replace($ext, ($i + 1) . $targetExt, $this->sitemapFileName); + $targetSitemapFilepath = $this->basePath . $targetSitemapFilename; + + if ($this->isCompressionEnabled) { + $this->fs->copy($flushedSitemap, 'compress.zlib://' . $targetSitemapFilepath); + $this->fs->unlink($flushedSitemap); + } else { + $this->fs->rename($flushedSitemap, $targetSitemapFilepath); + } + $sitemapsUrls[] = htmlspecialchars($this->baseURL . '/' . $targetSitemapFilename, ENT_QUOTES); + $targetSitemapFilepaths[] = $targetSitemapFilepath; + } + + $targetSitemapIndexFilepath = $this->basePath . $this->sitemapIndexFileName; + $this->createSitemapIndex($sitemapsUrls, $targetSitemapIndexFilepath); + $this->generatedFiles['sitemaps_location'] = $targetSitemapFilepaths; + $this->generatedFiles['sitemaps_index_location'] = $targetSitemapIndexFilepath; + $this->generatedFiles['sitemaps_index_url'] = $this->baseURL . '/' . $this->sitemapIndexFileName; + } else { + throw new RuntimeException('failed to finalize, please add urls and flush first'); + } + } + + private function createSitemapIndex($sitemapsUrls, $sitemapIndexFileName) + { + $this->xmlWriter->flush(true); + $this->writeSitemapIndexStart(); + foreach ($sitemapsUrls as $sitemapsUrl) { + $this->writeSitemapIndexUrl($sitemapsUrl); + } + $this->writeSitemapIndexEnd(); + $this->fs->file_put_contents( + $sitemapIndexFileName, + $this->xmlWriter->flush(true), + FILE_APPEND + ); + } + + private function writeSitemapIndexStart() + { + $this->xmlWriter->startDocument("1.0", "UTF-8"); + $this->xmlWriter->writeComment(sprintf('generator-class="%s"', get_class($this))); + $this->xmlWriter->writeComment(sprintf('generator-version="%s"', $this->classVersion)); + $this->xmlWriter->writeComment(sprintf('generated-on="%s"', date('c'))); + $this->xmlWriter->startElement('sitemapindex'); + $this->xmlWriter->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9'); + $this->xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $this->xmlWriter->writeAttribute('xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd'); + } + + private function writeSitemapIndexUrl($url) + { + $this->xmlWriter->startElement('sitemap'); + $this->xmlWriter->writeElement('loc', htmlspecialchars($url, ENT_QUOTES)); + $this->xmlWriter->writeElement('lastmod', date('c')); + $this->xmlWriter->endElement(); // sitemap + } + + private function writeSitemapIndexEnd() + { + $this->xmlWriter->endElement(); // sitemapindex + $this->xmlWriter->endDocument(); + } + + /** + * @return array Array of previously generated files + */ + public function getGeneratedFiles(): array + { + return $this->generatedFiles; + } + + /** + * Will inform search engines about newly created sitemaps. + * Google, Ask, Bing and Yahoo will be noticed. + * If You don't pass yahooAppId, Yahoo still will be informed, + * but this method can be used once per day. If You will do this often, + * message that limit was exceeded will be returned from Yahoo. + * @param string $yahooAppId Your site Yahoo appid. + * @return array of messages and http codes from each search engine + * @access public + * @throws BadMethodCallException + */ + public function submitSitemap($yahooAppId = null): array + { + if (count($this->generatedFiles) === 0) { + throw new BadMethodCallException("To update robots.txt, call finalize() first."); + } + if (!$this->runtime->extension_loaded('curl')) { + throw new BadMethodCallException("cURL extension is needed to do submission."); + } + $searchEngines = $this->searchEngines; + $searchEngines[0] = isset($yahooAppId) ? + str_replace("USERID", $yahooAppId, $searchEngines[0][0]) : + $searchEngines[0][1]; + $result = []; + for ($i = 0; $i < count($searchEngines); $i++) { + $submitUrl = $searchEngines[$i] . htmlspecialchars($this->generatedFiles['sitemaps_index_url'], ENT_QUOTES); + $submitSite = $this->runtime->curl_init($submitUrl); + $this->runtime->curl_setopt($submitSite, CURLOPT_RETURNTRANSFER, true); + $responseContent = $this->runtime->curl_exec($submitSite); + $response = $this->runtime->curl_getinfo($submitSite); + $submitSiteShort = array_reverse(explode(".", parse_url($searchEngines[$i], PHP_URL_HOST))); + $result[] = [ + "site" => $submitSiteShort[1] . "." . $submitSiteShort[0], + "fullsite" => $submitUrl, + "http_code" => $response['http_code'], + "message" => str_replace("\n", " ", strip_tags($responseContent)), + ]; + } + return $result; + } + + /** + * Adds sitemap url to robots.txt file located in basePath. + * If robots.txt file exists, + * the function will append sitemap url to file. + * If robots.txt does not exist, + * the function will create new robots.txt file with sample content and sitemap url. + * @access public + * @throws BadMethodCallException + * @throws RuntimeException + */ + public function updateRobots(): SitemapGenerator + { + if (count($this->generatedFiles) === 0) { + throw new BadMethodCallException("To update robots.txt, call finalize() first."); + } + + $robotsFilePath = $this->basePath . $this->robotsFileName; + + $robotsFileContent = $this->createNewRobotsContentFromFile($robotsFilePath); + + $this->fs->file_put_contents($robotsFilePath, $robotsFileContent); + + return $this; + } + + /** + * @param $filepath + * @return string + */ + private function createNewRobotsContentFromFile($filepath): string + { + if ($this->fs->file_exists($filepath)) { + $robotsFileContent = ""; + $robotsFile = explode(PHP_EOL, $this->fs->file_get_contents($filepath)); + foreach ($robotsFile as $key => $value) { + if (substr($value, 0, 8) == 'Sitemap:') { + unset($robotsFile[$key]); + } else { + $robotsFileContent .= $value . PHP_EOL; + } + } + } else { + $robotsFileContent = $this->getSampleRobotsContent(); + } + + $robotsFileContent .= "Sitemap: {$this->generatedFiles['sitemaps_index_url']}"; + + return $robotsFileContent; + } + + /** + * @return string + * @access private + */ + private function getSampleRobotsContent(): string + { + return implode(PHP_EOL, $this->sampleRobotsLines) . PHP_EOL; + } +} diff --git a/core/core.php b/core/core.php index 029409cf..b915ca85 100755 --- a/core/core.php +++ b/core/core.php @@ -741,22 +741,26 @@ class common { $timezone = $this->getData(['config','timezone']); - $sitemap = new \Icamys\SitemapGenerator\SitemapGenerator(helper::baseurl()); + $outputDir = getcwd(); + + $sitemap = new \Icamys\SitemapGenerator\SitemapGenerator(helper::baseurl(false),$outputDir); // will create also compressed (gzipped) sitemap - $sitemap->createGZipFile = true; + $sitemap->enableCompression(); // determine how many urls should be put into one file // according to standard protocol 50000 is maximum value (see http://www.sitemaps.org/protocol.html) - $sitemap->maxURLsPerSitemap = 50000; + $sitemap->setMaxUrlsPerSitemap(50000); // sitemap file name - $sitemap->sitemapFileName = "sitemap.xml"; + $sitemap->setSitemapFileName("sitemap.xml"); + + // Set the sitemap index file name + $sitemap->setSitemapIndexFileName("sitemap-index.xml"); $datetime = new DateTime(date('c')); $datetime->format(DateTime::ATOM); // Updated ISO8601 - // sitemap index file name - $sitemap->sitemapIndexFileName = "sitemap-index.xml"; + foreach($this->getHierarchy(null, null, null) as $parentPageId => $childrenPageIds) { // Exclure les barres et les pages non publiques et les pages masquées if ($this->getData(['page',$parentPageId,'group']) !== 0 || @@ -798,17 +802,22 @@ class common { } - // generating internally a sitemap - $sitemap->createSitemap(); + // Flush all stored urls from memory to the disk and close all necessary tags. + $sitemap->flush(); - // writing early generated sitemap to file - $sitemap->writeSitemap(); + // Move flushed files to their final location. Compress if the option is enabled. + $sitemap->finalize(); + + // Update robots.txt file in output directory or create a new one + $sitemap->updateRobots(); + + // Submit your sitemaps to Google, Yahoo, Bing and Ask.com + $sitemap->submitSitemap(); return(file_exists('sitemap.xml')); } - /* * Création d'une miniature * Fonction utilisée lors de la mise à jour d'une version 9 à une version 10 @@ -1602,11 +1611,6 @@ class common { if ($this->getData(['core', 'dataVersion']) < 10405) { $this->setData(['core', 'dataVersion', 10405]); } - // Version 10.4.06 - if ($this->getData(['core', 'dataVersion']) < 10406) { - $this->removeDir ('core/class/sitemap'); - $this->setData(['core', 'dataVersion', 10406]); - } } } From cb8b5d4de13855ad0effa0bc5b83cf06ed88014e Mon Sep 17 00:00:00 2001 From: fredtempez Date: Wed, 10 Mar 2021 18:55:15 +0100 Subject: [PATCH 07/12] Revert "Merge branch '10500' into 11000" This reverts commit 6d576a16a6412c7e7a8d9332fc85054954376d31, reversing changes made to 7766c16ed94dc4b18996b52c8c8606b143233bbf. --- core/core.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/core.php b/core/core.php index b915ca85..051e6b94 100755 --- a/core/core.php +++ b/core/core.php @@ -1611,6 +1611,30 @@ class common { if ($this->getData(['core', 'dataVersion']) < 10405) { $this->setData(['core', 'dataVersion', 10405]); } + + // Version 11.0.00 + if ($this->getData(['core', 'dataVersion']) < 11000) { + + // Option de déconnexion auto activée + $this->setData(['config','autoDisconnect',true]); + + // Mettre à jour les données de langue + $this->setData(['config','translate','scriptGoogle', false ]); + $this->setData(['config','translate','showCredits', false ]); + $this->setData(['config','translate','autoDetect', false ]); + $this->setData(['config','translate','admin', false ]); + $this->setData(['config','translate','fr', false ]); + $this->setData(['config','translate','de', false ]); + $this->setData(['config','translate','en', false ]); + $this->setData(['config','translate','es', false ]); + $this->setData(['config','translate','it', false ]); + $this->setData(['config','translate','nl', false ]); + $this->setData(['config','translate','pt', false ]); + + $this->setData(['core', 'dataVersion', 11000]); + + + } } } From ddbeedd4d5ecb821e48ba0fac49deed798faf018 Mon Sep 17 00:00:00 2001 From: fredtempez Date: Wed, 10 Mar 2021 19:00:43 +0100 Subject: [PATCH 08/12] Php 7.2 --- README.md | 6 +++--- index.php | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cb8fa959..8466d956 100755 --- a/README.md +++ b/README.md @@ -9,12 +9,12 @@ ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remij ## Configuration recommandée -* PHP 5.6 ou plus +* PHP 7.2 ou plus * Support de .htaccess -## Téléchargement de ZwiICMS +## Téléchargement de ZwiiCMS -Pour télécharger la dernière version publiée, il faut vous rendre sur la page de téléchargemet du [site](https://zwiicms.fr/telechargements) +Pour télécharger la dernière version publiée, il faut vous rendre sur la page de téléchargement du [site](https://zwiicms.fr/telechargements) La version github est une **version de développement** qui peut encore contenir des bugs mais elle vous permet de tester les dernières nouveautés. Cette version n'est pas recommandée en production. diff --git a/index.php b/index.php index 3e6b954b..2867c446 100755 --- a/index.php +++ b/index.php @@ -22,8 +22,8 @@ session_start(); /** * Vérification de la version de PHP */ -if(version_compare(PHP_VERSION, '5.6.0', '<')) { - exit('PHP 5.6+ required.'); +if(version_compare(PHP_VERSION, '7.2.0', '<')) { + exit('PHP 7.2+ required.'); } /* From c180f65af8c0cd9c93355966b38f9a061ff704ba Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Thu, 11 Mar 2021 10:06:59 +0100 Subject: [PATCH 09/12] curl avant stream open --- core/class/helper.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/class/helper.class.php b/core/class/helper.class.php index 2f505797..a0866708 100755 --- a/core/class/helper.class.php +++ b/core/class/helper.class.php @@ -53,18 +53,18 @@ class helper { if(function_exists('file_get_contents') && ini_get('allow_url_fopen') ){ $url_get_contents_data = @file_get_contents($url); // Masque un warning éventuel - }elseif(function_exists('fopen') && - function_exists('stream_get_contents') && - ini_get('allow_url_fopen')){ - $handle = fopen ($url, "r"); - $url_get_contents_data = stream_get_contents($handle); }elseif(function_exists('curl_version')){ $ch = curl_init(); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, $url); $url_get_contents_data = curl_exec($ch); - curl_close($ch); + curl_close($ch); + }elseif(function_exists('fopen') && + function_exists('stream_get_contents') && + ini_get('allow_url_fopen')){ + $handle = fopen ($url, "r"); + $url_get_contents_data = stream_get_contents($handle); }else{ $url_get_contents_data = false; } From 2a197e886bd7bf026c834275ab92e5acdef79043 Mon Sep 17 00:00:00 2001 From: SylvainLelievre Date: Thu, 11 Mar 2021 11:37:46 +0100 Subject: [PATCH 10/12] =?UTF-8?q?Syst=C3=A8me=20d'aide=20dans=20core.js.ph?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/core.js.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/core.js.php b/core/core.js.php index 456cd067..5bed7595 100755 --- a/core/core.js.php +++ b/core/core.js.php @@ -474,6 +474,20 @@ $(document).ready(function(){ }; }); + /** + * Active le système d'aide interne + * + */ + + $(".helpDisplayButton").on({ + mouseenter: function () { + $(".helpDisplayContent").slideDown(); + }, + mouseleave: function () { + $(".helpDisplayContent").slideUp(); + } + }); + /** * Remove ID Facebook from URL */ From 37cf776789a9a1437c86c7e57a21ec4b8d805648 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Thu, 11 Mar 2021 14:57:10 +0100 Subject: [PATCH 11/12] Pb sitemap avec proxy --- CHANGES.md | 5 ++++ core/core.php | 44 ++++++--------------------------- core/module/config/config.php | 44 ++++----------------------------- core/module/install/install.php | 2 -- 4 files changed, 17 insertions(+), 78 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 133b0b56..ca91add5 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,11 @@ # Changelog ## version 10.5.00 +A partir de cette version, les version de php inférieures à 7.2 ne sont plus supportées. +- Corrections : + - SiteMapGenerator 4.3.1 + - La classe SiteMapGenerator prend en charge la création/modification du fichier robots.txt + - Si un proxy est défini le sitemap n'est pas soumis aux moteurs de recherche afin d'éviter un timeout trop important. - Modifications : - Gestion des modules dans l'interface d'administration. diff --git a/core/core.php b/core/core.php index 051e6b94..97b22910 100755 --- a/core/core.php +++ b/core/core.php @@ -695,37 +695,6 @@ class common { return ($folder); } - /** - * Génère un fichier robots.txt à l'installation - * Si le fichier existe déjà les commandes sont ajoutées - */ - public function createRobots() { - - $robotValue = - PHP_EOL . - '# ZWII CONFIG ---------' . PHP_EOL . - 'User-agent: *' . PHP_EOL . - 'Allow: /site/file/' .PHP_EOL . - 'Disallow: /site/' .PHP_EOL . - 'Sitemap: ' . helper::baseUrl(false) . 'sitemap.xml' . PHP_EOL . - 'Sitemap: ' . helper::baseUrl(false) . 'sitemap.xml.gz' . PHP_EOL . - '# ZWII CONFIG ---------' . PHP_EOL ; - - if (file_exists('robots.txt')) { - return(file_put_contents( - 'robots.txt', - $robotValue, - FILE_APPEND - )); - } else { - // Sinon on crée un fichier - return(file_put_contents( - 'robots.txt', - $robotValue - )); - } - } - /** * Génère un fichier un fichier sitemap.xml @@ -740,9 +709,7 @@ class common { //require_once "core/vendor/sitemap/SitemapGenerator.php"; $timezone = $this->getData(['config','timezone']); - $outputDir = getcwd(); - $sitemap = new \Icamys\SitemapGenerator\SitemapGenerator(helper::baseurl(false),$outputDir); // will create also compressed (gzipped) sitemap @@ -753,10 +720,11 @@ class common { $sitemap->setMaxUrlsPerSitemap(50000); // sitemap file name - $sitemap->setSitemapFileName("sitemap.xml"); + $sitemap->setSitemapFileName( 'sitemap.xml') ; + // Set the sitemap index file name - $sitemap->setSitemapIndexFileName("sitemap-index.xml"); + $sitemap->setSitemapIndexFileName( 'sitemap-index.xml'); $datetime = new DateTime(date('c')); $datetime->format(DateTime::ATOM); // Updated ISO8601 @@ -812,9 +780,11 @@ class common { $sitemap->updateRobots(); // Submit your sitemaps to Google, Yahoo, Bing and Ask.com - $sitemap->submitSitemap(); + if (empty ($this->getData(['config','proxyType']) . $this->getData(['config','proxyUrl']) . ':' . $this->getData(['config','proxyPort'])) ) { + $sitemap->submitSitemap(); + } - return(file_exists('sitemap.xml')); + return(file_exists('sitemap.xml') && file_exists('robots.txt')); } diff --git a/core/module/config/config.php b/core/module/config/config.php index 7665cfd7..a2244036 100755 --- a/core/module/config/config.php +++ b/core/module/config/config.php @@ -20,7 +20,6 @@ class config extends common { 'backup' => self::GROUP_ADMIN, 'configMetaImage' => self::GROUP_ADMIN, 'generateFiles' => self::GROUP_ADMIN, - 'updateRobots' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN, 'advanced' => self::GROUP_ADMIN, 'manage' => self::GROUP_ADMIN, @@ -187,55 +186,22 @@ class config extends common { /** * Génére les fichiers pour les crawlers + * Sitemap compressé et non compressé + * Robots.txt */ public function generateFiles() { + // Mettre à jour le site map $successSitemap=$this->createSitemap(); - // Créer un fichier robots.txt - $successRobots=$this->updateRobots(); - if ( $successSitemap === true && - $successRobots >= 100) { - $success = true; - } else { - $success = false; - } // Valeurs en sortie $this->addOutput([ - 'notification' => ($successSitemap === true && $successRobots >= 100) ? 'Création réussie' : 'Echec d\'écriture', + 'notification' => $successSitemap ? 'Le sitemap a été mis à jour' : 'Echec d\'écriture, le site map n\'a pas été mis à jour', 'redirect' => helper::baseUrl() . 'config/advanced', - 'state' => ($successSitemap === true && $successRobots >=100) ? true : false + 'state' => $successSitemap ]); } - /** - * Met à jour un fichier robots.txt lors du changement de réécriture - */ - - private function updateRobots() { - // Créer le fichier robot si absent - if (!file_exists('robots.txt')) { - $this->createRobots(); - } - // backup - rename ('robots.txt','robots.bak'); - $fileold = fopen('robots.bak','r'); - $filenew = fopen('robots.txt','w'); - while(!feof($fileold)) { - $data = fgets($fileold); - if (strpos($data,'sitemap.xml') == 0) { - fwrite($filenew, $data); - } else { - fwrite($filenew, 'Sitemap: ' . helper::baseUrl(false) . 'sitemap.xml' . PHP_EOL); - fwrite($filenew, 'Sitemap: ' . helper::baseUrl(false) . 'sitemap.xml.gz' . PHP_EOL); - fwrite($filenew, '# ZWII CONFIG ---------' . PHP_EOL); - break; - } - } - fclose($fileold); - unlink('robots.bak'); - return(fclose($filenew)); - } /** * Sauvegarde des données diff --git a/core/module/install/install.php b/core/module/install/install.php index 1c2c1254..d5c7a419 100755 --- a/core/module/install/install.php +++ b/core/module/install/install.php @@ -103,8 +103,6 @@ class install extends common { } // Stocker le dossier d'installation $this->setData(['core', 'baseUrl', helper::baseUrl(false,false) ]); - // Générer un fichier robots.txt - $this->createRobots(); // Créer sitemap $this->createSitemap(); // Valeurs en sortie From 6ddec644acedcfee5fdf75292a47f7ce51944102 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Thu, 11 Mar 2021 14:59:12 +0100 Subject: [PATCH 12/12] merge change 10406 --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ca91add5..415c7e46 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,12 @@ A partir de cette version, les version de php inférieures à 7.2 ne sont plus s - Modifications : - Gestion des modules dans l'interface d'administration. +## version 10.4.06 +- Mise à jour : + - Annulation de la mise à jour SiteMapGenerator 4.3.1 et réinstallation de la version initiale. +- Modification : + - Méthode Curl pour la lecture de données par Url. + ## version 10.4.05 - Mise à jour : - SiteMapGenerator 4.3.1