Commit 0fc8bfc5 authored by Mike Rockétt's avatar Mike Rockétt

hidden pages, revert stylesheet

parent 142c8657
......@@ -13,13 +13,16 @@
// Require the classloader
require_once __DIR__ . '/ClassLoader.php';
use Rockett\Traits\BuilderTrait as BuildsSitemap;
use Rockett\Traits\DebugTrait as Debugs;
use Rockett\Traits\FieldsTrait as BuildsFields;
use Rockett\Sitemap\Elements\Url;
use Rockett\Sitemap\Elements\Urlset;
use Rockett\Sitemap\Output;
use Rockett\Sitemap\SubElements\Image;
use Rockett\Sitemap\SubElements\Link;
use Rockett\Traits\FieldsTrait;
class MarkupSitemap extends WireData implements Module
{
use BuildsFields, BuildsSitemap, Debugs;
use FieldsTrait;
/**
* Image fields: each field is mapped to the relavent
......@@ -41,28 +44,26 @@ class MarkupSitemap extends WireData implements Module
'images' => false,
'page' => false,
'children' => false,
]
],
];
/**
* Sßitemap URI
* Sitemap URI
*/
const SITEMAP_URI = '/sitemap.xml';
/**
* Current request URI
*
* @var string
*/
protected $requestUri = '';
/**
* Page selector
* Current UrlSet
*
* @reserved
* @var string
* @var Urlset
*/
protected $selector = '';
protected $urlSet;
/**
* Module installer
......@@ -239,21 +240,23 @@ class MarkupSitemap extends WireData implements Module
// Make sure that the root page exists.
if (!$this->pages->get($rootPage) instanceof NullPage) {
// Check for cached sitemap or regenerate if it doesn't exist
// $rootPageName = $this->sanitizer->pageName($rootPage);
$markupCache = $this->modules->MarkupCache;
if ((!$output = $markupCache->get('MarkupSitemap', 3600)) || $this->config->debug) {
$output = $this->buildNewSitemap($rootPage);
$markupCache->save($output);
header('X-SitemapRetrievedFromCache: no');
header('X-Cached-Sitemap: no');
} else {
header('X-SitemapRetrievedFromCache: yes');
header('X-Cached-Sitemap: yes');
}
header('Content-Type: application/xml', true, 200);
$event->return = $output;
// Prevent further hooks. This stops
// SystemNotifications from displaying a 404 event
// when /sitemap.xml is requested. Additionall,
// when /sitemap.xml is requested. Additionally,
// it prevents further modification to the sitemap.
$event->replace = true;
$event->cancelHooks = true;
......@@ -399,4 +402,319 @@ class MarkupSitemap extends WireData implements Module
{
return $this->modules->isInstalled('LanguageSupportPageNames');
}
/**
* Add alternative languges, including current.
* @param Page $page
* @param Url $url
*/
protected function addAltLanguages($page, $url)
{
foreach ($this->languages as $altLanguage) {
if ($this->pageLanguageInvalid($altLanguage, $page)) {
continue;
}
if ($altLanguage->isDefault()
&& $this->pages->get(1)->name === 'home'
&& !$this->modules->LanguageSupportPageNames->useHomeSegment
&& !empty($this->sitemap_default_iso)) {
$languageIsoName = $this->sitemap_default_iso;
} else {
$languageIsoName = $this->pages->get(1)->localName($altLanguage);
}
$url->addSubElement(new Link($languageIsoName, $page->localHttpUrl($altLanguage)));
}
}
/**
* Generate an image tag for the current image in the loop
* @param Pageimage $image
* @param Language $language
* @return Image
*/
protected function addImage($image, $language = null)
{
$locImage = new Image($image->httpUrl);
foreach (self::IMAGE_FIELDS as $imageMetaMethod => $imageMetaValues) {
foreach (explode('|', $imageMetaValues) as $imageMetaValue) {
if ($language != null && !$language->isDefault() && $image->{"$imageMetaValue{$language->id}"}) {
$imageMetaValue .= $language->id;
}
if ($image->$imageMetaValue) {
if ($imageMetaMethod === 'License') {
// Skip invalid licence URLs
if (!filter_var($image->$imageMetaValue, FILTER_VALIDATE_URL)) {
continue;
}
}
$locImage->{"set{$imageMetaMethod}"}($image->$imageMetaValue);
}
}
}
return $locImage;
}
/**
* Add images to the current Url
* @param Url $url
* @param Language $language
*/
protected function addImages($page, $url, $language = null)
{
// Loop through declared image fields and skip non image fields
if ($this->sitemap_image_fields) {
foreach ($this->sitemap_image_fields as $imageFieldName) {
$page->of(false);
$imageField = $page->$imageFieldName;
if ($imageField) {
foreach ($imageField as $image) {
if ($image instanceof Pageimage || $image instanceof \ProcessWire\Pageimage) {
$url->addSubElement($this->addImage($image, $language));
}
}
}
}
}
}
/**
* Determine if a page can be included in the sitemap
* @param $page
* @param $options
* @return bool
*/
public function pageIsIncludible($page, $options)
{
// If it's the home page, it's always includible.
if ($page->id === 1) {
return true;
}
// If the page's template is excluded from accessing Sitemap,
// then it's not includible.
if (in_array($page->template->name, $this->sitemap_exclude_templates)) {
return false;
}
// Otherwise, check to see if the page itself has been excluded
// via Sitemap options.
return !$options['excludes']['page'];
}
/**
* Recursively add pages in each language with
* alternate language and image sub-elements.
* @param $page
*/
protected function addPages($page)
{
// Get the saved options for this page
$pageSitemapOptions = $this->modules->getConfig($this, "o{$page->id}");
// If the template that this page belongs to is not using sitemap options
// (per the module's current configuration), then we need to revert the keys
// in $pageSitemapOptions to their defaults so as to prevent their
// saved options from being used in this cycle.
if ($this->sitemap_include_templates !== null
&& !in_array($page->template->name, $this->sitemap_include_templates)
&& is_array($pageSitemapOptions)) {
array_walk_recursive($pageSitemapOptions, function (&$value) {
$value = false;
});
}
// If the page is viewable and not excluded or we’re working with the root page,
// begin generating the sitemap by adding pages recursively. (Root is always added.)
if ($page->viewable() && $this->pageIsIncludible($page, $pageSitemapOptions)) {
// If language support is enabled, then we need to loop through each language
// to generate <loc> for each language with all alternates, including the
// current language. Then add image references with multi-language support.
if ($this->siteUsesLanguageSupportPageNames()) {
foreach ($this->languages as $language) {
if ($this->pageLanguageInvalid($language, $page) || !$page->viewable($language)) {
continue;
}
$url = new Url($page->localHttpUrl($language));
$url->setLastMod(date('c', $page->modified));
$this->addAltLanguages($page, $url);
if ($pageSitemapOptions['priority']) {
$url->setPriority($this->formatPriorityFloat($pageSitemapOptions['priority']));
}
if (!$pageSitemapOptions['excludes']['images']) {
$this->addImages($page, $url, $language);
}
$this->urlSet->addUrl($url);
}
} else {
// If multi-language support is not enabled, then we only need to
// add the current URL to a new <loc>, along with images.
$url = new Url($page->httpUrl);
$url->setLastMod(date('c', $page->modified));
if ($pageSitemapOptions['priority']) {
$url->setPriority($this->formatPriorityFloat($pageSitemapOptions['priority']));
}
if (!$pageSitemapOptions['excludes']['images']) {
$this->addImages($page, $url);
}
$this->urlSet->addUrl($url);
}
}
// Check for children
if (!$pageSitemapOptions['excludes']['children']) {
// Build up the child selector.
$selector = "id!={$this->config->http404PageID}";
if ($this->sitemap_include_hidden) {
$selector = implode(',', [
'include=hidden',
'template!=admin',
$selector,
]);
}
// Check for children and include where possible.
if ($page->hasChildren($selector)) {
foreach ($page->children($selector) as $child) {
$this->addPages($child);
}
}
}
}
/**
* Build a new sitemap (called when cache doesn't have one or we're debugging)
* @return string
*/
protected function buildNewSitemap($rootPage)
{
$this->urlSet = new Urlset();
$this->addPages($this->pages->get($rootPage));
$sitemapOutput = new Output();
if ($this->sitemap_stylesheet) {
$sitemapOutput->addProcessingInstruction(
'xml-stylesheet',
'type="text/xsl" href="' . $this->getStylesheetUrl() . '"'
);
}
return $sitemapOutput->setIndented(true)->getOutput($this->urlSet);
}
/**
* If using a stylesheet, return its absolute URL.
* @return string
*/
protected function getStylesheetUrl()
{
if ($this->sitemap_stylesheet_custom
&& filter_var($this->sitemap_stylesheet_custom, FILTER_VALIDATE_URL)) {
return $this->sitemap_stylesheet_custom;
}
return $stylesheetPath = $this->urls->httpSiteModules . 'MarkupSitemap/assets/sitemap-stylesheet.xsl';
}
/**
* Dump vars and die.
*
* @param mixed $mixed The vars to dump
* @return void
*/
protected function dd()
{
$this->dump(func_get_args()) && die;
}
/**
* Dump vars.
*
* @param mixed $mixed The vars to dump
* @return void
*/
protected function dump()
{
$this->header();
array_map(
function ($mixed) {
var_dump($mixed);
},
func_get_args()
);
return true;
}
/**
* Prepare the content-type header
*
* @return void
*/
protected function header()
{
$header = 'Content-Type: text/plain';
if (!$this->headerPrepared($header)) {
header($header);
$this->timestamp = -microtime(true);
}
}
/**
* Determine if a header has been prepared.
*
* @param $header
* @return bool
*/
protected function headerPrepared($header)
{
$header = trim($header, ': ');
foreach (headers_list() as $listedHeader) {
if (stripos($listedHeader, $header) !== false) {
return true;
}
}
return false;
}
/**
* Print vars and die.
*
* @param mixed $mixed The vars to print
* @return void
*/
protected function pd()
{
$this->printVars(func_get_args()) && die;
}
/**
* Print vars.
*
* @param mixed $mixed The vars to print
* @return void
*/
protected function printVars()
{
$this->header();
array_map(
function ($mixed) {
print_r($mixed);
},
func_get_args()
);
return true;
}
/**
* Log things to a dedicated log file.
* @param $content
*/
protected function logme($content)
{
if ($this->config->debug) $this->log->save('markup-sitemap', $content);
}
}
......@@ -12,11 +12,11 @@
require_once __DIR__ . '/ClassLoader.php';
use Rockett\Traits\FieldsTrait as BuildsFields;
use Rockett\Traits\FieldsTrait;
class MarkupSitemapConfig extends ModuleConfig
{
use BuildsFields;
use FieldsTrait;
/**
* Get default condifguration, automatically passed to input fields.
......@@ -25,9 +25,9 @@ class MarkupSitemapConfig extends ModuleConfig
public function getDefaults()
{
return [
// This has been turned on by default due to the fact that
// the default XML output is not rendered properly (not sure why)
'sitemap_stylesheet' => true,
'sitemap_exclude_templates' => [],
'sitemap_include_hidden' => false,
];
}
......@@ -114,6 +114,14 @@ class MarkupSitemapConfig extends ModuleConfig
]));
}
$inputfields->add($this->buildInputField('Checkbox', [
'name+id' => 'sitemap_include_hidden',
'label' => $this->_('Include hidden or unpublished pages'),
'description' => $this->_('When scanning for children, those that are hidden or unpublished will be included when this option is enabled.'),
'icon' => 'eye-slash',
'collapsed' => Inputfield::collapsedBlank,
]));
// Create the stylesheet fieldset
$stylesheetFieldset = $this->buildInputField('Fieldset', [
'label' => $this->_('Stylesheet'),
......@@ -124,7 +132,6 @@ class MarkupSitemapConfig extends ModuleConfig
// Add the stylesheet checkbox
$stylesheetFieldset->add($this->buildInputField('Checkbox', [
'name+id' => 'sitemap_stylesheet',
// 'label' => $this->_('Sitemap Stylesheet'),
'label' => $this->_('Add a stylesheet to the sitemap'),
]));
......
......@@ -17,7 +17,6 @@
<xsl:if test="sitemap:sitemapindex">Index</xsl:if>
</title>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/css/tachyons.min.css"/>
<style>td{vertical-align:top}</style>
</head>
<body class="ph3 pb3 mid-gray">
<header class="mw8 pv4 center">
......@@ -44,7 +43,7 @@
sitemaps.
</xsl:when>
<xsl:otherwise>
This index contains
This sitemap contains
<strong class="blue"><xsl:value-of select="count(sitemap:urlset/sitemap:url)"/></strong>
URLs.
</xsl:otherwise>
......@@ -52,7 +51,7 @@
</h2>
<p>
This is an XML sitemap, meant for consumption by search engines.<br/>
You can find more information about XML sitemaps at <a href="https://www.sitemaps.org" class="link blue">www.sitemaps.org</a>.
You can find more information about XML sitemaps on <a href="https://sitemaps.org" class="link blue">sitemaps.org</a>.
</p>
</header>
......@@ -112,14 +111,17 @@
<xsl:template match="sitemap:urlset">
<div class="mw8 center">
<div class="overflow-auto">
<table class="w-100 f6 b--light-silver ba bw1" cellspacing="0">
<thead class="bg-light-silver">
<table class="w-100 f6 b--silver ba bw1" cellspacing="0">
<thead class="bg-silver">
<tr>
<th class="pa3 fw6 tl dark-gray" style="width:60px"></th>
<th class="pa3 fw6 tl dark-gray">URL</th>
<xsl:if test="sitemap:url/sitemap:changefreq">
<th class="pa3 fw6 tr dark-gray" style="width:130px">Change Freq.</th>
</xsl:if>
<xsl:if test="sitemap:url/sitemap:priority">
<th class="pa3 fw6 tr dark-gray" style="width:90px">Priority</th>
</xsl:if>
<xsl:if test="sitemap:url/sitemap:lastmod">
<th class="pa3 fw6 tr dark-gray" style="width:200px">Last Modified</th>
</xsl:if>
......@@ -139,20 +141,16 @@
</td>
<td class="pa3 bb b--silver">
<p>
<a href="{$loc}" class="f5 link blue b">
<a href="{$loc}" class="link blue">
<xsl:value-of select="sitemap:loc"/>
</a>
<xsl:if test="sitemap:priority">
<small class="dib ml2 mr2 ph1 pv1 tracked lh-solid white bg-light-blue br-pill">
Priority: <xsl:value-of select="sitemap:priority"/>
</small>
</xsl:if>
</p>
<xsl:apply-templates select="xhtml:*"/>
<xsl:apply-templates select="image:*"/>
<xsl:apply-templates select="video:*"/>
</td>
<xsl:apply-templates select="sitemap:changefreq"/>
<xsl:apply-templates select="sitemap:priority"/>
<xsl:if test="sitemap:lastmod">
<td class="pa3 tr bb b--silver">
<xsl:value-of select="concat(substring(sitemap:lastmod, 0, 11), concat(' ', substring(sitemap:lastmod, 12, 5)), concat(' ', substring(sitemap:lastmod, 20, 6)))"/>
......@@ -186,19 +184,19 @@
</a>
<xsl:if test="@hreflang">
<small class="dib mr2 ph1 pv1 tracked lh-solid white bg-green br-pill">
<small class="dib mr2 ph1 pv1 tracked lh-solid white bg-silver br-pill">
<xsl:value-of select="@hreflang"/>
</small>
</xsl:if>
<xsl:if test="@rel">
<small class="dib mr2 ph2 pv1 tracked lh-solid white bg-light-silver br-pill">
<small class="dib mr2 ph2 pv1 tracked lh-solid white bg-silver br-pill">
<xsl:value-of select="@rel"/>
</small>
</xsl:if>
<xsl:if test="@media">
<small class="dib mr2 ph2 pv1 tracked lh-solid white bg-light-silver br-pill">
<small class="dib mr2 ph2 pv1 tracked lh-solid white bg-silver br-pill">
<xsl:value-of select="@media"/>
</small>
</xsl:if>
......@@ -210,24 +208,17 @@
<xsl:variable name="loc">
<xsl:value-of select="image:loc"/>
</xsl:variable>
<xsl:variable name="license_loc">
<xsl:value-of select="image:license"/>
</xsl:variable>
<p>
<strong>Image: </strong>
<a href="{$loc}" class="mr2 link blue">
<xsl:value-of select="image:loc"/>
</a>
<xsl:if test="image:license">
<small>
<a href="{$license_loc}" class="dib mr2 ph2 pv1 tracked lh-solid link white bg-light-silver hover-bg-blue br-pill">license</a>
</small>
</xsl:if>
<xsl:if test="image:caption">
<span class="i gray">
<xsl:value-of select="image:caption"/>
</span>
</xsl:if>
<xsl:apply-templates/>
</p>
</xsl:template>
......@@ -257,9 +248,9 @@
</xsl:otherwise>
</xsl:choose>
</a>
<small>
<a href="{$thumb_loc}" class="dib mr2 ph2 pv1 tracked lh-solid link white bg-light-silver hover-bg-blue br-pill">thumb</a>
</small>
<a href="{$thumb_loc}" class="dib mr2 ph2 pv1 tracked lh-solid link white bg-silver hover-bg-blue br-pill">
thumb
</a>
<xsl:if test="video:title">
<span class="i gray">
<xsl:value-of select="video:title"/>
......
<?php
/**
* Sitemap builder trait. Contains all methods needed for
* putting a new sitemap together.
*
* @author Mike Rockett
* @license ISC
*/
namespace Rockett\Traits;
use Rockett\Sitemap\Elements\Url;
use Rockett\Sitemap\Elements\Urlset;
use Rockett\Sitemap\Output;
use Rockett\Sitemap\SubElements\Image;
use Rockett\Sitemap\SubElements\Link;
trait BuilderTrait
{
/**
* Current UrlSet
*
* @var Urlset
*/
protected $urlSet;
/**
* Add alternative languges, including current.
* @param Page $page
* @param Url $url
*/
protected function addAltLanguages($page, $url)
{
foreach ($this->languages as $altLanguage) {
if ($this->pageLanguageInvalid($altLanguage, $page)) {
continue;
}
if ($altLanguage->isDefault()
&& $this->pages->get(1)->name === 'home'