vendor/contao/core-bundle/src/Resources/contao/library/Contao/Automator.php line 166

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of Contao.
  4.  *
  5.  * (c) Leo Feyer
  6.  *
  7.  * @license LGPL-3.0-or-later
  8.  */
  9. namespace Contao;
  10. use FOS\HttpCache\CacheInvalidator;
  11. use FOS\HttpCacheBundle\CacheManager;
  12. use Symfony\Component\Console\Input\ArgvInput;
  13. use Symfony\Component\Console\Output\NullOutput;
  14. /**
  15.  * Provide methods to run automated jobs.
  16.  */
  17. class Automator extends System
  18. {
  19.     /**
  20.      * Make the constructor public
  21.      */
  22.     public function __construct()
  23.     {
  24.         parent::__construct();
  25.     }
  26.     /**
  27.      * Purge the search tables
  28.      */
  29.     public function purgeSearchTables()
  30.     {
  31.         // The search indexer is disabled
  32.         if (!System::getContainer()->has('contao.search.indexer'))
  33.         {
  34.             return;
  35.         }
  36.         $searchIndexer System::getContainer()->get('contao.search.indexer');
  37.         // Clear the index
  38.         $searchIndexer->clear();
  39.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the search tables');
  40.     }
  41.     /**
  42.      * Purge the undo table
  43.      */
  44.     public function purgeUndoTable()
  45.     {
  46.         $objDatabase Database::getInstance();
  47.         // Truncate the table
  48.         $objDatabase->execute("TRUNCATE TABLE tl_undo");
  49.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the undo table');
  50.     }
  51.     /**
  52.      * Purge the version table
  53.      */
  54.     public function purgeVersionTable()
  55.     {
  56.         $objDatabase Database::getInstance();
  57.         // Truncate the table
  58.         $objDatabase->execute("TRUNCATE TABLE tl_version");
  59.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the version table');
  60.     }
  61.     /**
  62.      * Purge the system log
  63.      */
  64.     public function purgeSystemLog()
  65.     {
  66.         $objDatabase Database::getInstance();
  67.         // Truncate the table
  68.         $objDatabase->execute("TRUNCATE TABLE tl_log");
  69.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the system log');
  70.     }
  71.     /**
  72.      * Purge the crawl queue
  73.      */
  74.     public function purgeCrawlQueue()
  75.     {
  76.         $objDatabase Database::getInstance();
  77.         // Truncate the table
  78.         $objDatabase->execute("TRUNCATE TABLE tl_crawl_queue");
  79.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the crawl queue');
  80.     }
  81.     /**
  82.      * Purge the image cache
  83.      */
  84.     public function purgeImageCache()
  85.     {
  86.         $container System::getContainer();
  87.         $strTargetPath StringUtil::stripRootDir($container->getParameter('contao.image.target_dir'));
  88.         $strRootDir $container->getParameter('kernel.project_dir');
  89.         // Walk through the subfolders
  90.         foreach (Folder::scan($strRootDir '/' $strTargetPath) as $dir)
  91.         {
  92.             if (strncmp($dir'.'1) !== 0)
  93.             {
  94.                 $objFolder = new Folder($strTargetPath '/' $dir);
  95.                 $objFolder->purge();
  96.             }
  97.         }
  98.         // Also empty the shared cache so there are no links to deleted images
  99.         $this->purgePageCache();
  100.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the image cache');
  101.     }
  102.     /**
  103.      * Purge the preview cache
  104.      */
  105.     public function purgePreviewCache()
  106.     {
  107.         $container System::getContainer();
  108.         $strTargetPath StringUtil::stripRootDir($container->getParameter('contao.image.preview.target_dir'));
  109.         $strRootDir $container->getParameter('kernel.project_dir');
  110.         // Walk through the subfolders
  111.         foreach (Folder::scan($strRootDir '/' $strTargetPath) as $dir)
  112.         {
  113.             if (strncmp($dir'.'1) !== 0)
  114.             {
  115.                 $objFolder = new Folder($strTargetPath '/' $dir);
  116.                 $objFolder->purge();
  117.             }
  118.         }
  119.         // Also empty the shared cache so there are no links to deleted previews
  120.         $this->purgePageCache();
  121.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the preview cache');
  122.     }
  123.     /**
  124.      * Purge the script cache
  125.      */
  126.     public function purgeScriptCache()
  127.     {
  128.         // assets/js and assets/css
  129.         foreach (array('assets/js''assets/css') as $dir)
  130.         {
  131.             // Purge the folder
  132.             $objFolder = new Folder($dir);
  133.             $objFolder->purge();
  134.         }
  135.         // Recreate the internal style sheets
  136.         $this->import(StyleSheets::class, 'StyleSheets');
  137.         $this->StyleSheets->updateStyleSheets();
  138.         // Also empty the shared cache so there are no links to deleted scripts
  139.         $this->purgePageCache();
  140.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the script cache');
  141.     }
  142.     /**
  143.      * Purge the shared cache
  144.      */
  145.     public function purgePageCache()
  146.     {
  147.         $container System::getContainer();
  148.         if (!$container->has('fos_http_cache.cache_manager'))
  149.         {
  150.             System::getContainer()->get('monolog.logger.contao.error')->error('Cannot purge the shared cache; invalid reverse proxy configuration');
  151.             return;
  152.         }
  153.         /** @var CacheManager $cacheManager */
  154.         $cacheManager $container->get('fos_http_cache.cache_manager');
  155.         if (!$cacheManager->supports(CacheInvalidator::CLEAR))
  156.         {
  157.             System::getContainer()->get('monolog.logger.contao.error')->error('Cannot purge the shared cache; invalid reverse proxy configuration');
  158.             return;
  159.         }
  160.         $cacheManager->clearCache();
  161.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the shared cache');
  162.     }
  163.     /**
  164.      * Purge the search cache
  165.      *
  166.      * @deprecated Deprecated since Contao 4.12, to be removed in Contao 5.0.
  167.      */
  168.     public function purgeSearchCache()
  169.     {
  170.         trigger_deprecation('contao/core-bundle''4.12''Using "Contao\Automator::purgeSearchCache()" has been deprecated and will no longer work in Contao 5.0.');
  171.         $strCacheDir StringUtil::stripRootDir(System::getContainer()->getParameter('kernel.cache_dir'));
  172.         $objFolder = new Folder($strCacheDir '/contao/search');
  173.         $objFolder->purge();
  174.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the search cache');
  175.     }
  176.     /**
  177.      * Purge the internal cache
  178.      */
  179.     public function purgeInternalCache()
  180.     {
  181.         $container System::getContainer();
  182.         $clearer $container->get('contao.cache.clearer');
  183.         $clearer->clear($container->getParameter('kernel.cache_dir'));
  184.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the internal cache');
  185.     }
  186.     /**
  187.      * Purge the temp folder
  188.      */
  189.     public function purgeTempFolder()
  190.     {
  191.         // Purge the folder
  192.         $objFolder = new Folder('system/tmp');
  193.         $objFolder->purge();
  194.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the temp folder');
  195.     }
  196.     /**
  197.      * Purge registrations that have not been activated within 24 hours
  198.      */
  199.     public function purgeRegistrations()
  200.     {
  201.         $objMember MemberModel::findExpiredRegistrations();
  202.         if ($objMember === null)
  203.         {
  204.             return;
  205.         }
  206.         while ($objMember->next())
  207.         {
  208.             $objMember->delete();
  209.         }
  210.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the unactivated member registrations');
  211.     }
  212.     /**
  213.      * Purge opt-in tokens
  214.      */
  215.     public function purgeOptInTokens()
  216.     {
  217.         $optIn System::getContainer()->get('contao.opt_in');
  218.         $optIn->purgeTokens();
  219.         System::getContainer()->get('monolog.logger.contao.cron')->info('Purged the expired double opt-in tokens');
  220.     }
  221.     /**
  222.      * Remove old XML files from the share directory
  223.      *
  224.      * @param boolean $blnReturn If true, only return the finds and don't delete
  225.      *
  226.      * @return array An array of old XML files
  227.      */
  228.     public function purgeXmlFiles($blnReturn=false)
  229.     {
  230.         $arrFeeds = array();
  231.         // HOOK: preserve third party feeds
  232.         if (isset($GLOBALS['TL_HOOKS']['removeOldFeeds']) && \is_array($GLOBALS['TL_HOOKS']['removeOldFeeds']))
  233.         {
  234.             foreach ($GLOBALS['TL_HOOKS']['removeOldFeeds'] as $callback)
  235.             {
  236.                 $this->import($callback[0]);
  237.                 $arrFeeds array_merge($arrFeeds$this->{$callback[0]}->{$callback[1]}());
  238.             }
  239.         }
  240.         // Delete the old files
  241.         if (!$blnReturn)
  242.         {
  243.             $shareDir System::getContainer()->getParameter('contao.web_dir') . '/share';
  244.             foreach (Folder::scan($shareDir) as $file)
  245.             {
  246.                 if (is_dir($shareDir '/' $file))
  247.                 {
  248.                     continue; // see #6652
  249.                 }
  250.                 $objFile = new File(StringUtil::stripRootDir($shareDir) . '/' $file);
  251.                 if ($objFile->extension == 'xml' && !\in_array($objFile->filename$arrFeeds))
  252.                 {
  253.                     $objFile->delete();
  254.                 }
  255.             }
  256.         }
  257.         return $arrFeeds;
  258.     }
  259.     /**
  260.      * Invalidate the cached XML sitemaps
  261.      *
  262.      * @param integer $intId The root page ID
  263.      */
  264.     public function generateSitemap($intId=0)
  265.     {
  266.         $container System::getContainer();
  267.         if (!$container->has('fos_http_cache.cache_manager'))
  268.         {
  269.             return;
  270.         }
  271.         /** @var CacheManager $cacheManager */
  272.         $cacheManager $container->get('fos_http_cache.cache_manager');
  273.         $tag 'contao.sitemap';
  274.         if ($intId 0)
  275.         {
  276.             $tag .= '.' $intId;
  277.         }
  278.         $cacheManager->invalidateTags(array($tag));
  279.     }
  280.     /**
  281.      * Regenerate the XML files
  282.      */
  283.     public function generateXmlFiles()
  284.     {
  285.         // Sitemaps
  286.         $this->generateSitemap();
  287.         // HOOK: add custom jobs
  288.         if (isset($GLOBALS['TL_HOOKS']['generateXmlFiles']) && \is_array($GLOBALS['TL_HOOKS']['generateXmlFiles']))
  289.         {
  290.             foreach ($GLOBALS['TL_HOOKS']['generateXmlFiles'] as $callback)
  291.             {
  292.                 $this->import($callback[0]);
  293.                 $this->{$callback[0]}->{$callback[1]}();
  294.             }
  295.         }
  296.         // Also empty the shared cache so there are no links to deleted files
  297.         $this->purgePageCache();
  298.         System::getContainer()->get('monolog.logger.contao.cron')->info('Regenerated the XML files');
  299.     }
  300.     /**
  301.      * Generate the symlinks in the public folder
  302.      */
  303.     public function generateSymlinks()
  304.     {
  305.         $container System::getContainer();
  306.         $command $container->get('contao.command.symlinks');
  307.         $status $command->run(new ArgvInput(array()), new NullOutput());
  308.         if ($status 0)
  309.         {
  310.             System::getContainer()->get('monolog.logger.contao.error')->error('The symlinks could not be regenerated');
  311.         }
  312.         else
  313.         {
  314.             System::getContainer()->get('monolog.logger.contao.cron')->info('Regenerated the symlinks');
  315.         }
  316.     }
  317.     /**
  318.      * Generate the internal cache
  319.      */
  320.     public function generateInternalCache()
  321.     {
  322.         $container System::getContainer();
  323.         $warmer $container->get('contao.cache.warmer');
  324.         $warmer->warmUp($container->getParameter('kernel.cache_dir'));
  325.         System::getContainer()->get('monolog.logger.contao.cron')->info('Generated the internal cache');
  326.     }
  327.     /**
  328.      * Rotate the log files
  329.      *
  330.      * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0.
  331.      *             Use the logger service instead, which rotates its log files automatically.
  332.      */
  333.     public function rotateLogs()
  334.     {
  335.         trigger_deprecation('contao/core-bundle''4.0''Using "Contao\Automator::rotateLogs()" has been deprecated and will no longer work in Contao 5.0. Use the logger service instead, which rotates its log files automatically.');
  336.         $projectDir System::getContainer()->getParameter('kernel.project_dir');
  337.         $arrFiles preg_grep('/\.log$/'Folder::scan($projectDir '/system/logs'));
  338.         foreach ($arrFiles as $strFile)
  339.         {
  340.             // Ignore Monolog log files (see #2579)
  341.             if (preg_match('/-\d{4}-\d{2}-\d{2}\.log$/'$strFile))
  342.             {
  343.                 continue;
  344.             }
  345.             $objFile = new File('system/logs/' $strFile '.9');
  346.             // Delete the oldest file
  347.             if ($objFile->exists())
  348.             {
  349.                 $objFile->delete();
  350.             }
  351.             // Rotate the files (e.g. error.log.4 becomes error.log.5)
  352.             for ($i=8$i>0$i--)
  353.             {
  354.                 $strGzName 'system/logs/' $strFile '.' $i;
  355.                 if (file_exists($projectDir '/' $strGzName))
  356.                 {
  357.                     $objFile = new File($strGzName);
  358.                     $objFile->renameTo('system/logs/' $strFile '.' . ($i+1));
  359.                 }
  360.             }
  361.             // Add .1 to the latest file
  362.             $objFile = new File('system/logs/' $strFile);
  363.             $objFile->renameTo('system/logs/' $strFile '.1');
  364.         }
  365.     }
  366. }
  367. class_alias(Automator::class, 'Automator');