bnomei/kirby3-robots-txt

View on GitHub
classes/Robotstxt.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php

declare(strict_types=1);

namespace Bnomei;

use Kirby\Toolkit\A;

final class Robotstxt
{
    public function __construct(
        private array $options = [],
        private array $txt = [],
    ) {
        $defaults = [
            'debug' => option('debug'),
            'content' => option('bnomei.robots-txt.content'),
            'groups' => option('bnomei.robots-txt.groups'),
            'sitemap' => option('bnomei.robots-txt.sitemap'),
        ];
        $this->options = array_merge($defaults, $options);

        foreach ($this->options as $key => $call) {
            if ($call instanceof \Closure) {
                $this->options[$key] = $call();
            }
        }

        $this->addContent($this->option('content'))
            ->addGroups($this->option('groups'))
            ->addSitemap($this->option('sitemap'));
    }

    public function option(string $key): mixed
    {
        return A::get($this->options, $key);
    }

    public function toArray(): ?array
    {
        return count($this->txt) ? $this->txt : null;
    }

    public function toTxt(): ?string
    {
        return count($this->txt) ? implode(PHP_EOL, $this->txt).PHP_EOL : null;
    }

    private function addContent(mixed $content = null): self
    {
        if (empty($content)) {
            return $this;
        }
        if (is_string($content)) {
            $this->txt[] = $content;
        }

        return $this;
    }

    private function addGroups(mixed $groups = null): self
    {
        if (empty($groups)) {
            return $this;
        }
        if ($this->option('debug')) {
            $groups = ['*' => ['disallow' => ['/']]];
        }
        if (is_array($groups)) {
            $this->processGroupsArray($groups);
        } elseif (is_string($groups)) {
            $this->txt[] = $groups;
        }

        return $this;
    }

    private function processGroupsArray(array $groups): void
    {
        foreach ($groups as $useragent => $group) {
            $this->txt[] = 'user-agent: '.$useragent;
            if (is_array($group)) {
                $this->processGroupFields($group);
            }
        }
    }

    private function processGroupFields(array $group): void
    {
        foreach ($group as $field => $values) {
            if (is_array($values)) {
                $this->processFieldValues($field, $values);
            }
        }
    }

    private function processFieldValues(string $field, array $values): void
    {
        foreach ($values as $value) {
            $this->txt[] = implode('', [$field, ': ', $value]);
        }
    }

    private function hasSitemapFromKnownPlugin(): bool
    {
        return count(array_filter([
            option('omz13.xmlsitemap.disable') === false,
            option('fabianmichael.meta.sitemap') === true,
            option('tobimori.seo.robots.active') === false,
            option('johannschopplich.helpers.sitemap.enable') === true && option('johannschopplich.helpers.robots.enable') === false,
            option('bnomei.feed.sitemap.enable') === true,
        ])) > 0;
    }

    private function addSitemap(mixed $sitemap = null): self
    {
        // @codeCoverageIgnoreStart
        if ($this->hasSitemapFromKnownPlugin()) {
            $this->txt[] = 'sitemap: '.url('/sitemap.xml');

            return $this;
        }
        // @codeCoverageIgnoreEnd

        if (! is_string($sitemap)) {
            return $this;
        }

        $this->txt[] = 'sitemap: '.url($sitemap);

        return $this;
    }
}