Skip to content

Instantly share code, notes, and snippets.

@garvinhicking
Created November 9, 2023 10:09
Show Gist options
  • Save garvinhicking/1f3159f53853ab8f35e9100fbb5f7c33 to your computer and use it in GitHub Desktop.
Save garvinhicking/1f3159f53853ab8f35e9100fbb5f7c33 to your computer and use it in GitHub Desktop.
SpiderApplication - `php cli.php`
<?php
namespace Composer;
$GLOBALS['_composer_bin_dir'] = '/var/www/html/vendor/bin/';
$GLOBALS['_composer_autoload_path'] = '/var/www/html/vendor/autoload.php';
call_user_func(function() {
$classLoader = require ($GLOBALS['_composer_autoload_path'] ?? __DIR__ . '/../vendor/autoload.php');
require __DIR__ . '/SpiderApplication.php';
\TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(1, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI);
$core = \TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, true)->get(\TYPO3\CMS\Core\Console\SpiderApplication::class)->run();
});
<?php
namespace TYPO3\CMS\Core\Console;
use Symfony\Component\Console\Application as SymfonyConsoleApplication;
use Symfony\Component\Console\Exception\ExceptionInterface;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use TYPO3\CMS\Core\Adapter\EventDispatcherAdapter as SymfonyEventDispatcher;
use TYPO3\CMS\Core\Authentication\CommandLineUserAuthentication;
use TYPO3\CMS\Core\Configuration\ConfigurationManager;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Context\DateTimeAspect;
use TYPO3\CMS\Core\Context\UserAspect;
use TYPO3\CMS\Core\Context\VisibilityAspect;
use TYPO3\CMS\Core\Context\WorkspaceAspect;
use TYPO3\CMS\Core\Core\ApplicationInterface;
use TYPO3\CMS\Core\Core\BootService;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Core\Localization\LanguageServiceFactory;
class SpiderApplication implements ApplicationInterface
{
protected Context $context;
protected CommandRegistry $commandRegistry;
protected ConfigurationManager $configurationManager;
protected BootService $bootService;
protected LanguageServiceFactory $languageServiceFactory;
protected SymfonyConsoleApplication $application;
public function __construct(
Context $context,
CommandRegistry $commandRegistry,
EventDispatcherInterface $eventDispatcher,
ConfigurationManager $configurationMananger,
BootService $bootService,
LanguageServiceFactory $languageServiceFactory
)
{
$this->context = $context;
$this->commandRegistry = $commandRegistry;
$this->configurationManager = $configurationMananger;
$this->bootService = $bootService;
$this->languageServiceFactory = $languageServiceFactory;
$this->application = new Application('TYPO3 CMS', (new Typo3Version())->getVersion());
$this->application->setAutoExit(FALSE);
$this->application->setDispatcher($eventDispatcher);
$this->application->setCommandLoader($commandRegistry);
}
/**
* Run the Symfony Console application in this TYPO3 application
*/
public function run()
{
$input = new ArgvInput();
$output = new ConsoleOutput();
// Do a full container boot if command is not a 1:1 matching low-level command
$container = $this->bootService->getContainer();
$eventDispatcher = $container->get(SymfonyEventDispatcher::class);
$commandRegistry = $container->get(CommandRegistry::class);
$this->application->setDispatcher($eventDispatcher);
$this->application->setCommandLoader($commandRegistry);
$this->context = $container->get(Context::class);
$this->bootService->loadExtLocalconfDatabaseAndExtTables();
$this->initializeContext();
// create the BE_USER object (not logged in yet)
Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
$GLOBALS['LANG'] = $this->languageServiceFactory->createFromUserPreferences($GLOBALS['BE_USER']);
// Make sure output is not buffered, so command-line output and interaction can take place
ob_clean();
$exitCode = $this->application->run($input, $output);
exit($exitCode);
}
/**
* Initializes the Context used for accessing data and finding out the current state of the application
*/
protected function initializeContext(): void
{
$this->context->setAspect('date', new DateTimeAspect(new \DateTimeImmutable('@' . $GLOBALS['EXEC_TIME'])));
$this->context->setAspect('visibility', new VisibilityAspect(TRUE, TRUE));
$this->context->setAspect('workspace', new WorkspaceAspect(0));
$this->context->setAspect('backend.user', new UserAspect(NULL));
}
}
@garvinhicking
Copy link
Author

Solution, accessing SiteFinder directly:

<?php
namespace Composer;

use Symfony\Component\Finder\Finder;
use TYPO3\CMS\Core\Configuration\Loader\YamlFileLoader;
use TYPO3\CMS\Core\Utility\GeneralUtility;

$GLOBALS['_composer_bin_dir'] = '/var/www/html/vendor/bin/';
$GLOBALS['_composer_autoload_path'] = '/var/www/html/vendor/autoload.php';

call_user_func(function() {
    $classLoader = require ($GLOBALS['_composer_autoload_path'] ?? __DIR__ . '/../vendor/autoload.php');
    \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::run(1, \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI);
    $core = \TYPO3\CMS\Core\Core\Bootstrap::init($classLoader, true);

    $finder = new Finder();
    try {
        $finder->files()->depth(0)->name('config.yaml')->in('/var/www/html/config/sites/*');
    } catch (Exception $e) {
        $finder = [];
    }

    $loader = GeneralUtility::makeInstance(YamlFileLoader::class);

    $siteConfiguration = [];
    foreach ($finder as $fileInfo) {
        $configuration = $loader->load((string)$fileInfo);
        $identifier = basename($fileInfo->getPath());
        $siteConfiguration[$identifier] = $configuration;
    }

    foreach($siteConfiguration AS $site) {
        $variants = $baseVariants = [];

        if (is_array($site['baseVariants'])) {
            foreach($site['baseVariants'] AS $variant) {
                # Simplification: We grab all things ddev
                if (stristr($variant['base'], 'ddev.site')) {
                    $variants[] = $variant['base'] . $site['base'];
                    $baseVariants[] = $variant['base'];
                }
            }
        } else {
            $variants[] = $site['base'];
        }

        if (is_array($site['languages'])) {
            foreach($site['languages'] AS $languageKey => $siteLanguage) {
                // Add each language to each baseVariant
                foreach($baseVariants AS $variant) {
                    $variants[] = $variant . $siteLanguage['base'];
                }
            }
        }

        foreach($variants AS $url) {
            echo "[*] Spider: $url\n";
        }
    }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment