| Total Complexity | 40 |
| Total Lines | 313 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like SitemapIndexTemplate often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use SitemapIndexTemplate, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 35 | class SitemapIndexTemplate extends FrontendTemplate implements SitemapInterface |
||
| 36 | { |
||
| 37 | // Constants |
||
| 38 | // ========================================================================= |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @event RegisterSitemapsEvent The event that is triggered when registering |
||
| 42 | * additional sitemaps for the sitemap index. |
||
| 43 | * |
||
| 44 | * --- |
||
| 45 | * ```php |
||
| 46 | * use nystudio107\seomatic\events\RegisterSitemapsEvent; |
||
| 47 | * use nystudio107\seomatic\models\SitemapIndexTemplate; |
||
| 48 | * use yii\base\Event; |
||
| 49 | * Event::on(SitemapIndexTemplate::class, SitemapIndexTemplate::EVENT_REGISTER_SITEMAPS, function(RegisterSitemapsEvent $e) { |
||
| 50 | * $e->sitemaps[] = [ |
||
| 51 | * 'loc' => $url, |
||
| 52 | * 'lastmod' => $lastMod, |
||
| 53 | * ]; |
||
| 54 | * }); |
||
| 55 | * ``` |
||
| 56 | */ |
||
| 57 | public const EVENT_REGISTER_SITEMAPS = 'registerSitemaps'; |
||
| 58 | |||
| 59 | public const TEMPLATE_TYPE = 'SitemapIndexTemplate'; |
||
| 60 | |||
| 61 | public const CACHE_KEY = 'seomatic_sitemap_index'; |
||
| 62 | |||
| 63 | public const SITEMAP_INDEX_CACHE_TAG = 'seomatic_sitemap_index'; |
||
| 64 | |||
| 65 | // Static Methods |
||
| 66 | // ========================================================================= |
||
| 67 | |||
| 68 | /** |
||
| 69 | * @param array $config |
||
| 70 | * |
||
| 71 | * @return null|SitemapIndexTemplate |
||
| 72 | */ |
||
| 73 | public static function create(array $config = []) |
||
| 74 | { |
||
| 75 | $defaults = [ |
||
| 76 | 'path' => 'sitemaps-<groupId:\d+>-sitemap.xml', |
||
| 77 | 'template' => '', |
||
| 78 | 'controller' => 'sitemap', |
||
| 79 | 'action' => 'sitemap-index', |
||
| 80 | ]; |
||
| 81 | $config = array_merge($config, $defaults); |
||
| 82 | |||
| 83 | return new SitemapIndexTemplate($config); |
||
| 84 | } |
||
| 85 | |||
| 86 | // Public Properties |
||
| 87 | // ========================================================================= |
||
| 88 | |||
| 89 | // Public Methods |
||
| 90 | // ========================================================================= |
||
| 91 | |||
| 92 | /** |
||
| 93 | * @inheritdoc |
||
| 94 | */ |
||
| 95 | public function rules(): array |
||
| 96 | { |
||
| 97 | $rules = parent::rules(); |
||
| 98 | $rules = array_merge($rules, [ |
||
| 99 | ]); |
||
| 100 | |||
| 101 | return $rules; |
||
| 102 | } |
||
| 103 | |||
| 104 | /** |
||
| 105 | * @inheritdoc |
||
| 106 | */ |
||
| 107 | public function fields(): array |
||
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Get the filename of the sitemap index. |
||
| 114 | * |
||
| 115 | * @param int $groupId |
||
| 116 | * @return string |
||
| 117 | */ |
||
| 118 | public function getFilename(int $groupId): string |
||
| 121 | } |
||
| 122 | |||
| 123 | /** |
||
| 124 | * @inheritdoc |
||
| 125 | * |
||
| 126 | * @throws NotFoundHttpException if the sitemap.xml doesn't exist |
||
| 127 | */ |
||
| 128 | public function render(array $params = []): string |
||
| 129 | { |
||
| 130 | $cache = Craft::$app->getCache(); |
||
| 131 | $groupId = $params['groupId']; |
||
| 132 | $siteId = $params['siteId']; |
||
| 133 | if (Seomatic::$settings->siteGroupsSeparate) { |
||
| 134 | /** @var SiteGroup|null $siteGroup */ |
||
| 135 | $siteGroup = Craft::$app->getSites()->getGroupById($groupId); |
||
| 136 | if ($siteGroup === null) { |
||
| 137 | throw new NotFoundHttpException(Craft::t('seomatic', 'Sitemap.xml not found for groupId {groupId}', [ |
||
| 138 | 'groupId' => $groupId, |
||
| 139 | ])); |
||
| 140 | } |
||
| 141 | $groupSiteIds = $siteGroup->getSiteIds(); |
||
| 142 | } else { |
||
| 143 | $groupSiteIds = Craft::$app->getSites()->allSiteIds; |
||
| 144 | } |
||
| 145 | |||
| 146 | $dependency = new TagDependency([ |
||
| 147 | 'tags' => [ |
||
| 148 | self::GLOBAL_SITEMAP_CACHE_TAG, |
||
| 149 | self::SITEMAP_INDEX_CACHE_TAG, |
||
| 150 | ], |
||
| 151 | ]); |
||
| 152 | |||
| 153 | return $cache->getOrSet(self::CACHE_KEY . $groupId . '.' . $siteId, function() use ($groupSiteIds, $siteId) { |
||
| 154 | Craft::info( |
||
| 155 | 'Sitemap index cache miss', |
||
| 156 | __METHOD__ |
||
| 157 | ); |
||
| 158 | $lines = []; |
||
| 159 | // Sitemap index XML header and opening tag |
||
| 160 | $lines[] = '<?xml version="1.0" encoding="UTF-8"?>'; |
||
| 161 | $lines[] = '<?xml-stylesheet type="text/xsl" href="sitemap.xsl"?>'; |
||
| 162 | $lines[] = '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'; |
||
| 163 | // One sitemap entry for each MeteBundle |
||
| 164 | $metaBundles = Seomatic::$plugin->metaBundles->getContentMetaBundlesForSiteId($siteId); |
||
| 165 | Seomatic::$plugin->metaBundles->pruneVestigialMetaBundles($metaBundles); |
||
| 166 | /** @var MetaBundle $metaBundle */ |
||
| 167 | foreach ($metaBundles as $metaBundle) { |
||
| 168 | $sitemapUrls = $metaBundle->metaSitemapVars->sitemapUrls; |
||
| 169 | // Check to see if robots is `none` or `no index` |
||
| 170 | $robotsEnabled = true; |
||
| 171 | if (!empty($metaBundle->metaGlobalVars->robots)) { |
||
| 172 | $robotsEnabled = $metaBundle->metaGlobalVars->robots !== 'none' && |
||
| 173 | $metaBundle->metaGlobalVars->robots !== 'noindex'; |
||
| 174 | } |
||
| 175 | if (Seomatic::$plugin->sitemaps->anyEntryTypeHasSitemapUrls($metaBundle)) { |
||
| 176 | $robotsEnabled = true; |
||
| 177 | $sitemapUrls = true; |
||
| 178 | } |
||
| 179 | // Only add in a sitemap entry if it meets our criteria |
||
| 180 | if (in_array($metaBundle->sourceSiteId, $groupSiteIds, false) |
||
| 181 | && $sitemapUrls |
||
| 182 | && $robotsEnabled) { |
||
| 183 | // Get all of the elements for this meta bundle type |
||
| 184 | $seoElement = Seomatic::$plugin->seoElements->getSeoElementByMetaBundleType($metaBundle->sourceBundleType); |
||
| 185 | $totalElements = 0; |
||
| 186 | $pageCount = 0; |
||
| 187 | |||
| 188 | if ($seoElement !== null) { |
||
| 189 | // Ensure `null` so that the resulting element query is correct |
||
| 190 | if (empty($metaBundle->metaSitemapVars->sitemapLimit)) { |
||
| 191 | $metaBundle->metaSitemapVars->sitemapLimit = null; |
||
| 192 | } |
||
| 193 | |||
| 194 | $totalElements = $seoElement::sitemapElementsQuery($metaBundle)->count(); |
||
| 195 | |||
| 196 | if ($metaBundle->metaSitemapVars->sitemapLimit && ($totalElements > $metaBundle->metaSitemapVars->sitemapLimit)) { |
||
| 197 | $totalElements = $metaBundle->metaSitemapVars->sitemapLimit; |
||
| 198 | } |
||
| 199 | |||
| 200 | $pageSize = $metaBundle->metaSitemapVars->sitemapPageSize; |
||
| 201 | $pageCount = (!empty($pageSize) && $pageSize > 0) ? ceil($totalElements / $pageSize) : 1; |
||
| 202 | } |
||
| 203 | |||
| 204 | // Only add a sitemap to the sitemap index if there's at least 1 element in the resulting sitemap |
||
| 205 | if ($totalElements > 0 && $pageCount > 0) { |
||
| 206 | for ($page = 1; $page <= $pageCount; $page++) { |
||
| 207 | $sitemapUrl = Seomatic::$plugin->sitemaps->sitemapUrlForBundle( |
||
| 208 | $metaBundle->sourceBundleType, |
||
| 209 | $metaBundle->sourceHandle, |
||
| 210 | $metaBundle->sourceSiteId, |
||
| 211 | $pageCount > 1 ? $page : 0 // No paging, if only one page |
||
| 212 | ); |
||
| 213 | |||
| 214 | $lines[] = '<sitemap>'; |
||
| 215 | $lines[] = '<loc>'; |
||
| 216 | $lines[] = Html::encode($sitemapUrl); |
||
| 217 | $lines[] = '</loc>'; |
||
| 218 | |||
| 219 | if ($metaBundle->sourceDateUpdated !== null) { |
||
| 220 | $lines[] = '<lastmod>'; |
||
| 221 | $lines[] = $metaBundle->sourceDateUpdated->format(DateTime::W3C); |
||
| 222 | $lines[] = '</lastmod>'; |
||
| 223 | } |
||
| 224 | |||
| 225 | $lines[] = '</sitemap>'; |
||
| 226 | } |
||
| 227 | } |
||
| 228 | } |
||
| 229 | } |
||
| 230 | // Custom sitemap entries |
||
| 231 | $metaBundle = Seomatic::$plugin->metaBundles->getGlobalMetaBundle($siteId, false); |
||
| 232 | if ($metaBundle !== null) { |
||
| 233 | $this->addAdditionalSitemapUrls($metaBundle, $siteId, $lines); |
||
| 234 | $this->addAdditionalSitemaps($metaBundle, $siteId, $lines); |
||
| 235 | } |
||
| 236 | // Sitemap index closing tag |
||
| 237 | $lines[] = '</sitemapindex>'; |
||
| 238 | |||
| 239 | return implode('', $lines); |
||
| 240 | }, Seomatic::$cacheDuration, $dependency); |
||
| 241 | } |
||
| 242 | |||
| 243 | /** |
||
| 244 | * Invalidate the sitemap index cache |
||
| 245 | */ |
||
| 246 | public function invalidateCache() |
||
| 253 | ); |
||
| 254 | } |
||
| 255 | |||
| 256 | // Protected Methods |
||
| 257 | // ========================================================================= |
||
| 258 | |||
| 259 | /** |
||
| 260 | * Add an additional sitemap to the sitemap index, coming from the global |
||
| 261 | * meta bundle metaSiteVars->additionalSitemaps |
||
| 262 | * |
||
| 263 | * @param MetaBundle $metaBundle |
||
| 264 | * @param int $groupSiteId |
||
| 265 | * @param array $lines |
||
| 266 | * |
||
| 267 | * @throws Exception |
||
| 268 | */ |
||
| 269 | protected function addAdditionalSitemaps(MetaBundle $metaBundle, int $groupSiteId, array &$lines) |
||
| 297 | } |
||
| 298 | } |
||
| 299 | } |
||
| 300 | } |
||
| 301 | |||
| 302 | /** |
||
| 303 | * Add an additional "custom" sitemap to the sitemap index, with URLs coming from |
||
| 304 | * the global meta bundle metaSiteVars->additionalSitemapUrls |
||
| 305 | * |
||
| 306 | * @param MetaBundle $metaBundle |
||
| 307 | * @param int $groupSiteId |
||
| 308 | * @param array $lines |
||
| 309 | * |
||
| 310 | * @throws Exception |
||
| 311 | */ |
||
| 312 | protected function addAdditionalSitemapUrls(MetaBundle $metaBundle, int $groupSiteId, array &$lines) |
||
| 348 | } |
||
| 349 | } |
||
| 351 |