This commit is contained in:
2026-03-11 15:57:27 +01:00
parent 481271c972
commit b4b460fd21
10775 changed files with 2071579 additions and 26409 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,143 @@
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Thin.ttf') format('truetype');
font-weight: 100;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-ThinItalic.ttf') format('truetype');
font-weight: 100;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-ExtraLight.ttf') format('truetype');
font-weight: 200;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-ExtraLightItalic.ttf') format('truetype');
font-weight: 200;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Light.ttf') format('truetype');
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-LightItalic.ttf') format('truetype');
font-weight: 300;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-MediumItalic.ttf') format('truetype');
font-weight: 500;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-SemiBold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-SemiBoldItalic.ttf') format('truetype');
font-weight: 600;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Bold.ttf') format('truetype');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-BoldItalic.ttf') format('truetype');
font-weight: 700;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-ExtraBold.ttf') format('truetype');
font-weight: 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-ExtraBoldItalic.ttf') format('truetype');
font-weight: 800;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-Black.ttf') format('truetype');
font-weight: 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Albert Sans';
src: url('AlbertSans-BlackItalic.ttf') format('truetype');
font-weight: 900;
font-style: italic;
font-display: swap;
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 40 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,138 @@
@font-face {
font-family: 'grim';
src: url('fonts/grim.eot?dm8vk3');
src: url('fonts/grim.eot?dm8vk3#iefix') format('embedded-opentype'),
url('fonts/grim.ttf?dm8vk3') format('truetype'),
url('fonts/grim.woff?dm8vk3') format('woff'),
url('fonts/grim.svg?dm8vk3#grim') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
[class^="grim-icon-"], [class*=" grim-icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'grim' !important;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.grim-icon-external-link:before {
content: "\e924";
}
.grim-icon-user:before {
content: "\e923";
}
.grim-icon-base-tooltip:before {
content: "\e902";
}
.grim-icon-arrow-down_sm:before {
content: "\e903";
}
.grim-icon-arrow-down:before {
content: "\e904";
}
.grim-icon-arrow-left:before {
content: "\e905";
}
.grim-icon-arrow-up_sm:before {
content: "\e906";
}
.grim-icon-arrow-up:before {
content: "\e907";
}
.grim-icon-calendar:before {
content: "\e908";
}
.grim-icon-check_sm-Stroke:before {
content: "\e909";
}
.grim-icon-check-circle:before {
content: "\e90a";
}
.grim-icon-check:before {
content: "\e90b";
}
.grim-icon-chevron-down:before {
content: "\e90c";
}
.grim-icon-chevron-left:before {
content: "\e90d";
}
.grim-icon-chevron-right:before {
content: "\e90e";
}
.grim-icon-chevron-up:before {
content: "\e90f";
}
.grim-icon-copy:before {
content: "\e910";
}
.grim-icon-download:before {
content: "\e911";
}
.grim-icon-edit:before {
content: "\e912";
}
.grim-icon-file-text:before {
content: "\e913";
}
.grim-icon-google:before {
content: "\e914";
}
.grim-icon-help:before {
content: "\e915";
}
.grim-icon-home:before {
content: "\e916";
}
.grim-icon-image:before {
content: "\e917";
}
.grim-icon-information:before {
content: "\e918";
}
.grim-icon-logo-fill:before {
content: "\e919";
}
.grim-icon-logo-outline:before {
content: "\e91a";
}
.grim-icon-play-circle:before {
content: "\e91b";
}
.grim-icon-plus:before {
content: "\e91c";
}
.grim-icon-search:before {
content: "\e91d";
}
.grim-icon-single-sitemap:before {
content: "\e91e";
}
.grim-icon-sitemap-index:before {
content: "\e91f";
}
.grim-icon-sliders-horizontal:before {
content: "\e920";
}
.grim-icon-trash:before {
content: "\e921";
}
.grim-icon-upload:before {
content: "\e922";
}
.grim-icon-arrow-right:before {
content: "\e901";
}
.grim-icon-star:before {
content: "\e900";
}

View File

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-edit-post', 'wp-plugins', 'wp-primitives'), 'version' => 'a9b44345d0bf48d89310');

View File

@@ -0,0 +1,322 @@
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/@wordpress/icons/build-module/library/block-meta.js":
/*!**************************************************************************!*\
!*** ./node_modules/@wordpress/icons/build-module/library/block-meta.js ***!
\**************************************************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/primitives */ "@wordpress/primitives");
/* harmony import */ var _wordpress_primitives__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__);
/**
* WordPress dependencies
*/
const blockMeta = (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__.SVG, {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_primitives__WEBPACK_IMPORTED_MODULE_1__.Path, {
fillRule: "evenodd",
d: "M8.95 11.25H4v1.5h4.95v4.5H13V18c0 1.1.9 2 2 2h3c1.1 0 2-.9 2-2v-3c0-1.1-.9-2-2-2h-3c-1.1 0-2 .9-2 2v.75h-2.55v-7.5H13V9c0 1.1.9 2 2 2h3c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3c-1.1 0-2 .9-2 2v.75H8.95v4.5ZM14.5 15v3c0 .3.2.5.5.5h3c.3 0 .5-.2.5-.5v-3c0-.3-.2-.5-.5-.5h-3c-.3 0-.5.2-.5.5Zm0-6V6c0-.3.2-.5.5-.5h3c.3 0 .5.2.5.5v3c0 .3-.2.5-.5.5h-3c-.3 0-.5-.2-.5-.5Z",
clipRule: "evenodd"
}));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (blockMeta);
//# sourceMappingURL=block-meta.js.map
/***/ }),
/***/ "react":
/*!************************!*\
!*** external "React" ***!
\************************/
/***/ ((module) => {
module.exports = window["React"];
/***/ }),
/***/ "@wordpress/components":
/*!************************************!*\
!*** external ["wp","components"] ***!
\************************************/
/***/ ((module) => {
module.exports = window["wp"]["components"];
/***/ }),
/***/ "@wordpress/core-data":
/*!**********************************!*\
!*** external ["wp","coreData"] ***!
\**********************************/
/***/ ((module) => {
module.exports = window["wp"]["coreData"];
/***/ }),
/***/ "@wordpress/data":
/*!******************************!*\
!*** external ["wp","data"] ***!
\******************************/
/***/ ((module) => {
module.exports = window["wp"]["data"];
/***/ }),
/***/ "@wordpress/edit-post":
/*!**********************************!*\
!*** external ["wp","editPost"] ***!
\**********************************/
/***/ ((module) => {
module.exports = window["wp"]["editPost"];
/***/ }),
/***/ "@wordpress/plugins":
/*!*********************************!*\
!*** external ["wp","plugins"] ***!
\*********************************/
/***/ ((module) => {
module.exports = window["wp"]["plugins"];
/***/ }),
/***/ "@wordpress/primitives":
/*!************************************!*\
!*** external ["wp","primitives"] ***!
\************************************/
/***/ ((module) => {
module.exports = window["wp"]["primitives"];
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!************************************************!*\
!*** ./assets/gutenberg/src/plugin-sidebar.js ***!
\************************************************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/plugins */ "@wordpress/plugins");
/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_plugins__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _wordpress_edit_post__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/edit-post */ "@wordpress/edit-post");
/* harmony import */ var _wordpress_edit_post__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/data */ "@wordpress/data");
/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_data__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _wordpress_core_data__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @wordpress/core-data */ "@wordpress/core-data");
/* harmony import */ var _wordpress_core_data__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_wordpress_core_data__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _wordpress_icons__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @wordpress/icons */ "./node_modules/@wordpress/icons/build-module/library/block-meta.js");
/**
* WordPress dependencies
*/
const MetaBlockField = () => {
const postType = (0,_wordpress_data__WEBPACK_IMPORTED_MODULE_4__.useSelect)(select => select('core/editor').getCurrentPostType(), []);
const [meta, setMeta] = (0,_wordpress_core_data__WEBPACK_IMPORTED_MODULE_5__.useEntityProp)('postType', postType, 'meta');
const updateMeta = (key, value) => {
const element = document.getElementById(key);
if (element) {
if (element.type === 'checkbox') {
element.checked = value;
} else {
element.value = value;
}
}
setMeta({
...meta,
[key]: value
});
};
return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__.PanelBody, {
className: 'grim-gutenberg'
}, typeof sitemapSettings !== 'undefined' && !sitemapSettings?.isProEnabled && (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "pro-badge gutenberg"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("p", null, "This feature is available on Premium version"), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("a", {
href: "https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=sgg-plugin&utm_medium=meta-box-gutenberg&utm_campaign=xml_sitemap",
className: "grim-button secondary",
target: "_blank"
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("span", null, "Get Now"))), sitemapSettings?.isExcludeEnabled !== '0' && (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__.ToggleControl, {
className: "grim-toggle-gutenberg",
label: "Exclude from Sitemap",
checked: meta?._sitemap_exclude,
onChange: newValue => updateMeta('_sitemap_exclude', newValue)
}), sitemapSettings?.isPriorityEnabled !== '0' && (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("br", null), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__.SelectControl, {
className: 'grim-select-gutenberg',
label: "Post Priority",
value: meta?._sitemap_priority,
onChange: newValue => updateMeta('_sitemap_priority', newValue),
options: [{
label: 'Default',
value: ''
}, {
label: '0.0',
value: '0'
}, {
label: '0.1',
value: '1'
}, {
label: '0.2',
value: '2'
}, {
label: '0.3',
value: '3'
}, {
label: '0.4',
value: '4'
}, {
label: '0.5',
value: '5'
}, {
label: '0.6',
value: '6'
}, {
label: '0.7',
value: '7'
}, {
label: '0.8',
value: '8'
}, {
label: '0.9',
value: '9'
}, {
label: '1.0',
value: '10'
}]
})), sitemapSettings?.isFrequencyEnabled !== '0' && (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("br", null), (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_components__WEBPACK_IMPORTED_MODULE_3__.SelectControl, {
className: 'grim-select-gutenberg',
label: "Post Frequency",
value: meta?._sitemap_frequency,
onChange: newValue => updateMeta('_sitemap_frequency', newValue),
options: [{
label: 'Default',
value: ''
}, {
label: 'Always',
value: 'always'
}, {
label: 'Hourly',
value: 'hourly'
}, {
label: 'Daily',
value: 'daily'
}, {
label: 'Weekly',
value: 'weekly'
}, {
label: 'Monthly',
value: 'monthly'
}, {
label: 'Yearly',
value: 'yearly'
}, {
label: 'Never',
value: 'never'
}]
})), typeof sitemapSettings !== 'undefined' && !sitemapSettings?.isProEnabled && (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)("div", {
className: "pro-overlay gutenberg"
}));
};
(0,_wordpress_plugins__WEBPACK_IMPORTED_MODULE_1__.registerPlugin)('sitemap-settings', {
render: () => (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(_wordpress_edit_post__WEBPACK_IMPORTED_MODULE_2__.PluginSidebar, {
name: "sitemap-settings",
title: "XML Sitemaps",
icon: _wordpress_icons__WEBPACK_IMPORTED_MODULE_6__["default"]
}, (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(MetaBlockField, null))
});
})();
/******/ })()
;
//# sourceMappingURL=plugin-sidebar.js.map

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,4 @@
<svg width="88" height="74" viewBox="0 0 88 74" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M44 15.5V58M11 58V45C11 39.4772 15.4772 35 21 35H67C72.5228 35 77 39.4772 77 45V58" stroke="#121217" stroke-width="2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M34.625 3.84375C34.625 2.73918 35.5204 1.84375 36.625 1.84375H51.375C52.4796 1.84375 53.375 2.73918 53.375 3.84375V13.9062C53.375 15.0108 52.4796 15.9062 51.375 15.9062H36.625C35.5204 15.9062 34.625 15.0108 34.625 13.9062V3.84375ZM1.8125 60.0938C1.8125 58.9892 2.70793 58.0938 3.8125 58.0938H18.5625C19.6671 58.0938 20.5625 58.9892 20.5625 60.0938V70.1562C20.5625 71.2608 19.6671 72.1562 18.5625 72.1562H3.8125C2.70793 72.1562 1.8125 71.2608 1.8125 70.1562V60.0938ZM34.625 60.0938C34.625 58.9892 35.5204 58.0938 36.625 58.0938H51.375C52.4796 58.0938 53.375 58.9892 53.375 60.0938V70.1562C53.375 71.2608 52.4796 72.1562 51.375 72.1562H36.625C35.5204 72.1562 34.625 71.2608 34.625 70.1562V60.0938ZM67.4375 60.0938C67.4375 58.9892 68.3329 58.0938 69.4375 58.0938H84.1875C85.2921 58.0938 86.1875 58.9892 86.1875 60.0938V70.1562C86.1875 71.2608 85.2921 72.1562 84.1875 72.1562H69.4375C68.3329 72.1562 67.4375 71.2608 67.4375 70.1562V60.0938Z" stroke="#FF7113" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,4 @@
<svg width="82" height="78" viewBox="0 0 82 78" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M41 11V23M22.5 34V33C22.5 27.4772 26.9772 23 32.5 23H50C55.5228 23 60 27.4772 60 33V34M22.5 43.5V55.5M60 43.5V55.5M41 55.5V67M8.5 67V65.5C8.5 59.9772 12.9772 55.5 18.5 55.5H64C69.5228 55.5 74 59.9772 74 65.5V67" stroke="#8A8AA3" stroke-width="2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.2188 36.3125C15.2188 35.2079 16.1142 34.3125 17.2188 34.3125H27.2812C28.3858 34.3125 29.2812 35.2079 29.2812 36.3125V41.6875C29.2812 42.7921 28.3858 43.6875 27.2812 43.6875H17.2188C16.1142 43.6875 15.2188 42.7921 15.2188 41.6875V36.3125ZM52.7188 36.3125C52.7188 35.2079 53.6142 34.3125 54.7188 34.3125H64.7812C65.8858 34.3125 66.7812 35.2079 66.7812 36.3125V41.6875C66.7812 42.7921 65.8858 43.6875 64.7812 43.6875H54.7188C53.6142 43.6875 52.7188 42.7921 52.7188 41.6875V36.3125ZM33.9688 3.5C33.9688 2.39543 34.8642 1.5 35.9688 1.5H46.0312C47.1358 1.5 48.0312 2.39543 48.0312 3.5V8.875C48.0312 9.97957 47.1358 10.875 46.0312 10.875H35.9688C34.8642 10.875 33.9688 9.97957 33.9688 8.875V3.5ZM1.15625 69.125C1.15625 68.0204 2.05168 67.125 3.15625 67.125H13.2187C14.3233 67.125 15.2188 68.0204 15.2188 69.125V74.5C15.2188 75.6046 14.3233 76.5 13.2187 76.5H3.15625C2.05168 76.5 1.15625 75.6046 1.15625 74.5V69.125ZM33.9688 69.125C33.9688 68.0204 34.8642 67.125 35.9688 67.125H46.0312C47.1358 67.125 48.0312 68.0204 48.0312 69.125V74.5C48.0312 75.6046 47.1358 76.5 46.0312 76.5H35.9688C34.8642 76.5 33.9688 75.6046 33.9688 74.5V69.125ZM66.7812 69.125C66.7812 68.0204 67.6767 67.125 68.7813 67.125H78.8437C79.9483 67.125 80.8438 68.0204 80.8438 69.125V74.5C80.8438 75.6046 79.9483 76.5 78.8437 76.5H68.7813C67.6767 76.5 66.7812 75.6046 66.7812 74.5V69.125Z" stroke="#8A8AA3" stroke-width="2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -0,0 +1,16 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 64C0 37.528 0 24.292 6.66428 14.9662C8.95523 11.7604 11.7604 8.95523 14.9662 6.66428C24.292 0 37.528 0 64 0C90.472 0 103.708 0 113.034 6.66428C116.24 8.95523 119.045 11.7604 121.336 14.9662C128 24.292 128 37.528 128 64C128 90.472 128 103.708 121.336 113.034C119.045 116.24 116.24 119.045 113.034 121.336C103.708 128 90.472 128 64 128C37.528 128 24.292 128 14.9662 121.336C11.7604 119.045 8.95523 116.24 6.66428 113.034C0 103.708 0 90.472 0 64Z" fill="#FF7113"/>
<path d="M104.095 77.7414C98.4293 94.4046 82.6506 106.394 64.0715 106.394C57.8494 106.394 51.9415 105.048 46.6221 102.634C47.2161 101.889 47.6735 101.031 47.9563 100.097C52.8758 102.304 58.3301 103.533 64.0715 103.533C81.0488 103.533 95.518 92.7956 101.06 77.7414H104.095Z" fill="white"/>
<path d="M40.6609 92.9854C43.367 92.9855 45.5606 95.1791 45.5607 97.8852C45.5607 100.591 43.367 102.785 40.6609 102.785C37.9547 102.785 35.7608 100.591 35.7608 97.8852C35.7608 95.1791 37.9548 92.9854 40.6609 92.9854Z" fill="white"/>
<path d="M52.664 23.4254C52.7171 24.4033 52.8526 25.3592 53.0628 26.2868C36.659 31.0505 24.669 46.19 24.6689 64.1303C24.669 74.925 29.0105 84.7053 36.0418 91.822C35.2777 92.4051 34.6267 93.1289 34.1284 93.9554C26.515 86.312 21.8087 75.7708 21.8086 64.1303C21.8087 44.742 34.8645 28.4033 52.664 23.4254Z" fill="white"/>
<path d="M44.3903 71.1513C45.3976 73.9812 47.0338 76.6377 49.2992 78.903C55.3931 84.9969 64.315 86.5385 71.8404 83.5291C72.0926 84.5059 72.6566 85.3569 73.4189 85.9718C64.7581 89.675 54.3444 87.9935 47.2765 80.9257C44.6029 78.2521 42.7 75.0994 41.5677 71.7442C42.5604 71.7035 43.5103 71.4972 44.3903 71.1513Z" fill="white"/>
<path d="M76.3215 79.9187C77.6746 79.9187 78.7716 81.0157 78.7716 82.3688C78.7716 83.7219 77.6746 84.8189 76.3215 84.8189C74.9684 84.8189 73.8714 83.7219 73.8714 82.3688C73.8714 81.0157 74.9684 79.9187 76.3215 79.9187Z" fill="white"/>
<path d="M91.4552 54.9963C92.1003 54.9963 92.7269 55.1068 93.3351 55.328C93.9618 55.5491 94.5518 55.8807 95.1047 56.3231C95.6761 56.747 96.1738 57.3186 96.5977 58.0375C97.04 58.7563 97.2611 59.6134 97.2611 60.6087V70.5891C97.1505 71.695 96.5423 72.2941 95.4364 72.3863C94.9203 72.3863 94.4687 72.2205 94.0816 71.8887C93.713 71.5385 93.5289 71.1052 93.5289 70.5891V60.8297C93.5289 60.3874 93.4458 60.0188 93.28 59.7239C93.1141 59.4106 92.9296 59.1709 92.7269 59.005C92.5242 58.8207 92.3122 58.6915 92.0911 58.6178C91.8699 58.5256 91.6488 58.4799 91.4277 58.4798C91.2065 58.4798 90.9851 58.5256 90.7639 58.6178C90.5612 58.6915 90.3584 58.8207 90.1557 59.005C89.9529 59.1709 89.7688 59.4106 89.6029 59.7239C89.4371 60.0188 89.3448 60.3874 89.3264 60.8297V70.5891C89.2158 71.695 88.6076 72.2941 87.5017 72.3863C86.9856 72.3863 86.534 72.2205 86.1469 71.8887C85.7783 71.5385 85.5939 71.1052 85.5939 70.5891V60.8297C85.5939 60.3874 85.5111 60.0188 85.3453 59.7239C85.1794 59.4106 84.9949 59.1709 84.7922 59.005C84.5894 58.8207 84.3775 58.6915 84.1564 58.6178C83.9352 58.5256 83.7141 58.4799 83.493 58.4798C83.2718 58.4798 83.0504 58.5256 82.8292 58.6178C82.6265 58.6915 82.4237 58.8207 82.221 59.005C82.0182 59.1709 81.8341 59.4106 81.6682 59.7239C81.5024 60.0188 81.4101 60.3874 81.3917 60.8297V70.5891C81.2995 71.695 80.7004 72.2941 79.5946 72.3863C79.0785 72.3863 78.6269 72.2205 78.2398 71.8887C77.8712 71.5385 77.6867 71.1052 77.6867 70.5891V60.6087C77.7236 59.6134 77.9542 58.7563 78.3781 58.0375C78.802 57.3186 79.2997 56.747 79.8711 56.3231C80.4424 55.8808 81.0321 55.5491 81.6403 55.328C82.267 55.1068 82.8939 54.9963 83.5205 54.9963C84.1656 54.9963 84.7922 55.1068 85.4004 55.328C86.0271 55.5491 86.6262 55.8716 87.1976 56.2955C87.2897 56.3876 87.3911 56.4799 87.5017 56.572C87.5938 56.4799 87.6952 56.3876 87.8058 56.2955C88.3772 55.8716 88.9671 55.5491 89.5753 55.328C90.202 55.1068 90.8286 54.9963 91.4552 54.9963Z" fill="white"/>
<path d="M102.597 55.3004C103.113 55.3004 103.556 55.4753 103.924 55.8255C104.293 56.1572 104.486 56.5812 104.505 57.0972V63.7602C104.486 64.5159 104.533 65.2164 104.643 65.8615C104.772 66.4881 105.067 67.0503 105.528 67.5479C105.989 68.0455 106.569 68.3127 107.269 68.3496H116.117C116.633 68.368 117.057 68.5616 117.389 68.9303C117.739 69.2989 117.914 69.7414 117.914 70.2574C117.895 70.7551 117.711 71.1789 117.361 71.5291C117.029 71.8608 116.614 72.0361 116.117 72.0546H106.33C105.039 71.9808 103.97 71.5475 103.122 70.755C102.293 69.944 101.694 68.958 101.325 67.7969C100.975 66.6357 100.791 65.4006 100.772 64.0919V57.0972C100.791 56.5996 100.975 56.1848 101.325 55.8531C101.676 55.503 102.099 55.3188 102.597 55.3004Z" fill="white"/>
<path d="M57.9744 55.7703H58.251C59.578 55.8441 60.9512 56.5904 62.3704 58.0095C63.0707 58.7283 63.7157 59.5394 64.3055 60.4425C64.8953 59.5394 65.5496 58.7283 66.2684 58.0095C67.6692 56.5903 69.0332 55.8441 70.3603 55.7703H70.6368V55.7428H72.9591C73.4752 55.7428 73.9085 55.9269 74.2587 56.2955C74.6273 56.6457 74.8117 57.079 74.8117 57.5951C74.8117 58.1111 74.6272 58.5441 74.2587 58.8943C73.9085 59.2629 73.4752 59.4474 72.9591 59.4474H70.6368C69.9364 59.5211 69.2085 59.9819 68.4528 60.8297C67.6971 61.6776 67.0702 62.5716 66.5726 63.5116C66.462 63.7143 66.3514 63.9077 66.2409 64.0919C66.2777 64.1472 66.3147 64.2028 66.3515 64.2581C66.8492 65.2165 67.4758 66.1195 68.2314 66.9673C68.9871 67.8151 69.7154 68.2667 70.4158 68.322H72.7381C73.2541 68.322 73.6871 68.5065 74.0373 68.8751C74.4059 69.2253 74.5903 69.6583 74.5904 70.1743C74.5904 70.6904 74.4059 71.1329 74.0373 71.5015C73.6871 71.8517 73.2541 72.027 72.7381 72.027H70.1392C68.8122 71.9533 67.4482 71.2158 66.0474 69.815C65.4207 69.1699 64.84 68.4695 64.3055 67.7138C63.7709 68.4695 63.1905 69.1699 62.5638 69.815C61.163 71.2158 59.7991 71.9533 58.472 72.027H55.8732C55.3571 72.027 54.9147 71.8517 54.546 71.5015C54.1959 71.1329 54.0209 70.6904 54.0209 70.1743C54.0209 69.6584 54.2051 69.2252 54.5736 68.8751C54.9238 68.5065 55.3571 68.322 55.8732 68.322H58.1955C58.8959 68.2667 59.6241 67.8151 60.3798 66.9673C61.1354 66.1195 61.7621 65.2165 62.2597 64.2581C62.2966 64.2028 62.3335 64.1472 62.3704 64.0919C62.2598 63.9077 62.1492 63.7143 62.0387 63.5116C61.541 62.5716 60.9141 61.6776 60.1585 60.8297C59.4028 59.9819 58.6748 59.5211 57.9744 59.4474H55.6522C55.1361 59.4474 54.7028 59.2629 54.3526 58.8943C53.984 58.5441 53.7995 58.1111 53.7995 57.5951C53.7995 57.079 53.9748 56.6457 54.325 56.2955C54.6936 55.9269 55.1361 55.7428 55.6522 55.7428H57.9744V55.7703Z" fill="white"/>
<path d="M41.2052 58.1412C43.9114 58.1412 46.105 60.3352 46.105 63.0413C46.105 65.7474 43.9113 67.941 41.2052 67.9411C38.4991 67.9411 36.3051 65.7474 36.3051 63.0413C36.3051 60.3351 38.4991 58.1412 41.2052 58.1412Z" fill="white"/>
<path d="M47.2765 47.3349C54.1466 40.4648 64.1782 38.683 72.6881 41.9896C72.0309 42.693 71.5494 43.5626 71.3131 44.5284C63.9016 41.7957 55.2514 43.4054 49.2992 49.3576C47.5317 51.1251 46.1472 53.1305 45.1455 55.2707C44.2982 54.8401 43.371 54.5445 42.392 54.4111C43.5418 51.8451 45.17 49.4414 47.2765 47.3349Z" fill="white"/>
<path d="M86.0261 28.0102C94.252 33.0207 100.631 40.7621 103.905 49.975H100.855C97.756 41.9283 92.0934 35.1549 84.8673 30.6562C85.3246 29.8143 85.7131 28.9298 86.0261 28.0102Z" fill="white"/>
<path d="M76.8659 42.8971C78.5196 42.8971 79.8603 44.2377 79.8603 45.8915C79.8602 47.5452 78.5196 48.8859 76.8659 48.8859C75.2122 48.8858 73.8715 47.5452 73.8714 45.8915C73.8714 44.2378 75.2121 42.8972 76.8659 42.8971Z" fill="white"/>
<path d="M69.7883 11.3196C75.9523 11.3197 80.9493 16.3166 80.9493 22.4805C80.9493 28.6445 75.9523 33.6414 69.7883 33.6415C63.6243 33.6415 58.627 28.6446 58.627 22.4805C58.627 16.3165 63.6243 11.3196 69.7883 11.3196Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
"use strict";
jQuery(document).ready(function ($) {
$( document ).on( 'click', '.notice.is-dismissible .notice-dismiss, .sgg-notice', function(e) {
if ($(this).attr('href') === '#') {
e.preventDefault();
}
let $notice = $(this).closest('.notice');
let noticeId = $notice.attr('data-notice');
if(!noticeId) {
$notice = $(this).closest('.grim-notice-data');
noticeId = $notice.attr('data-notice');
}
if (!['sgg_rate', 'sgg_buy_pro'].includes(noticeId)) {
return;
}
$.ajax({
url: sggNotice.ajax_url,
method: 'post',
dataType: 'json',
data: {
action: 'sgg_disable_notice',
nonce: sggNotice.nonce,
notice: noticeId
}
});
$notice.fadeOut();
});
});

View File

@@ -0,0 +1,724 @@
"use strict";
jQuery(document).ready(function ($) {
/** Tabs */
let activeIndex = $('.nav-tab-active').index();
const $contentList = $('.nav-tabs-content .section'),
$tabsList = $('.nav-tab-wrapper a'),
$importSettings = $('#import-settings'),
$importSettingsInput = $('input[name="import_settings"]');
const savedTab = sessionStorage.getItem('sggActiveTab');
if (savedTab && $(`.nav-tab-wrapper a[data-id="${savedTab}"]`).length > 0) {
activeIndex = $(`.nav-tab-wrapper a[data-id="${savedTab}"]`).index();
}
$tabsList.removeClass('nav-tab-active');
$tabsList.eq(activeIndex).addClass('nav-tab-active');
$contentList.hide().eq(activeIndex).show();
$('.nav-tab-wrapper').on('click', 'a', function (e) {
e.preventDefault();
let $current = $(e.currentTarget),
index = $current.index(),
id = $current.data('id');
$tabsList.removeClass('nav-tab-active');
$current.addClass('nav-tab-active');
$contentList.hide().eq(index).show();
sessionStorage.setItem('sggActiveTab', id);
});
/** Dependency */
$('.has-dependency').click(function () {
if (this.type === 'radio') {
$(`input[name="${this.name}"]`).each(function () {
sgg_dependency(`.${$(this).data('target')}`, !this.checked);
});
} else {
sgg_dependency(`.${$(this).data('target')}`, !this.checked);
}
}).each(function () {
if (this.type === 'radio') {
$(`input[name="${this.name}"]`).each(function () {
sgg_dependency(`.${$(this).data('target')}`, !this.checked);
});
} else {
sgg_dependency(`.${$(this).data('target')}`, !this.checked);
}
});
/** Add Custom Sitemap */
$('#add_sitemap_url').on('click', function(e) {
e.preventDefault();
$('.no_urls').remove();
$('#custom_sitemaps').append('<tr>' +
'<td><input type="text" name="custom_sitemap_urls[]" class="grim-input"></td>' +
'<td><input type="datetime-local" name="custom_sitemap_lastmods[]" class="grim-input"></td>' +
'<td><a href="#" class="remove_url"><i class="grim-icon-trash"></i></a></td>' +
'</tr>');
});
/** Add Field */
$('#add_new_url').on('click', function(e) {
e.preventDefault();
$('.no_urls').remove();
$('#additional_urls').append('<tr>' +
'<td><input type="text" name="additional_urls[]" class="grim-input"></td>' +
'<td>' + $('#additional_priorities_selector').html() + '</td>' +
'<td>' + $('#additional_frequencies_selector').html() + '</td>' +
'<td><input type="datetime-local" name="additional_lastmods[]" class="grim-input"></td>' +
'<td><a href="#" class="remove_url"><i class="grim-icon-trash"></i></a></td>' +
'</tr>');
let $rows = $('#additional_urls').find('tr');
showAdditionalUrls();
normalizeVisibleRows($rows, 5);
});
/** Add Bulk URLs */
$('#add_bulk_urls').on('click', function(e) {
e.preventDefault();
$('.add-bulk-urls-section').removeClass('hidden');
showAdditionalUrls();
});
$('#run_add_bulk_urls').on('click', function(e) {
e.preventDefault();
const $bulk_urls = $('#bulk_urls');
// Add URLs
$bulk_urls.val().split('\n').forEach(url => {
if (url.trim() !== '') {
$('.no_urls').remove();
$('#additional_urls').append('<tr>' +
'<td><input type="text" name="additional_urls[]" class="grim-input" value="' + url.trim() + '"></td>' +
'<td>' + $('#additional_priorities_selector').html() + '</td>' +
'<td>' + $('#additional_frequencies_selector').html() + '</td>' +
'<td><input type="datetime-local" class="grim-input" name="additional_lastmods[]"></td>' +
'<td><a href="#" class="remove_url"><i class="grim-icon-trash"></i></a></td>' +
'</tr>');
}
});
$bulk_urls.val('');
$('.add-bulk-urls-section').addClass('hidden');
let $rows = $('#additional_urls').find('tr')
normalizeVisibleRows($rows, 5);
});
$('#cancel_add_bulk_urls').on('click', function(e) {
e.preventDefault();
$('#bulk_urls').val('');
$('.add-bulk-urls-section').addClass('hidden');
});
/** Remove Field */
$(document).on('click', '.remove_url', function(e) {
e.preventDefault();
const $row = $(this).closest('tr');
const $tbody = $row.closest('tbody');
$row.remove();
const $rows = $tbody.find('tr').not('.no_urls');
if ($tbody.find('tr').length === 0) {
$tbody.prepend(`
<tr class="no_urls">
<td colspan="5" align="center">${grimData.NoUrls}</td>
</tr>
`);
}
normalizeVisibleRows($rows, 5);
});
function normalizeVisibleRows($rows, limit = 5) {
let visibleCount = 0;
let $btn = $rows.closest('.grim-section').find('.grim-additional-urls-toggle');
if ( $btn && !$btn.hasClass('active')) {
$rows.each(function () {
const $row = $(this);
if (!$row.hasClass('grim-term-hidden') && visibleCount < limit) {
visibleCount++;
return;
}
if (visibleCount < limit) {
$row.removeClass('grim-term-hidden');
visibleCount++;
} else {
$row.addClass('grim-term-hidden');
}
});
}
toggleExpandButton($rows, $btn);
}
function showAdditionalUrls() {
let $rows = $('#additional_urls').find('tr')
let $btn = $rows.closest('.grim-section').find('.grim-additional-urls-toggle');
if ($btn.length && !$btn.hasClass('active')) {
$btn.addClass('active');
$rows.removeClass('grim-term-hidden');
$btn.find('span').text('Show Less');
}
}
function toggleExpandButton($rows, $toggle, limit = 5) {
$toggle.toggle($rows.length > limit);
}
/** Expand Additional URLs table */
$('.grim-additional-urls-toggle').on('click', function (e) {
e.preventDefault();
const $btn = $(this);
const $table = $btn.closest('.grim-section').find('.grim-additional-urls');
const $rows = $table.find('tbody tr').not('.no_urls');
$btn.toggleClass('active');
if ($btn.hasClass('active')) {
$rows.removeClass('grim-term-hidden');
$btn.find('span').text('Show Less');
} else {
$rows.each(function (index) {
if (index >= 5) {
$(this).addClass('grim-term-hidden');
}
});
$btn.find('span').text('Show More');
}
});
$('.grim-additional-urls tbody tr')
.not('.no_urls')
.each(function (index) {
let $btn = $(this).closest('.grim-section').find('.grim-additional-urls-toggle');
if (index >= 5) {
$btn.toggle(true);
$(this).addClass('grim-term-hidden');
} else {
$btn.toggle(false);
}
});
/** Expand */
$('.grim-expand-toggle').click(function (e) {
e.preventDefault();
const $btn = $(this);
const $rows = $btn.closest('.expand').find('tbody tr');
$btn.toggleClass('active');
if ($btn.hasClass('active')) {
$rows.removeClass('grim-term-hidden');
} else {
$rows.each(function(index){
if(index >= 5){
$(this).addClass('grim-term-hidden');
}
});
}
$btn.find('span').text(
$btn.hasClass('active') ? 'Show Less' : 'Show More'
);
});
/** Autocomplete */
$('.sgg-autocomplete').each(function() {
let $el = $(this);
let target = $el.data('target');
let type = $el.data('type');
let terms = sgg_get_terms(target);
sgg_render_terms(terms, target);
$el.autocomplete({
source: function (request, response) {
$.ajax({
url: sgg.ajax_url,
method: 'post',
dataType: 'json',
data: {
action: 'sgg_autocomplete_search',
term: request.term,
type
},
success: function (res) {
if (res?.success) {
response(res?.data);
} else {
response([{
label: res?.message,
value: 'false'
}])
}
}
});
},
minLength: 2,
open: function(event, ui) {
let menu = $(this).autocomplete('widget');
let currentTop = parseFloat(menu.css('top'));
menu.css('top', currentTop + 1 + 'px');
},
select: function (event, ui) {
terms = sgg_get_terms(target);
if (terms.findIndex(el => el.value == ui.item.value) === -1) {
terms.unshift(ui.item);
let $target = $(`#${target}`).siblings('.expand');
$target.children('.grim-expand-toggle').removeClass('active').find('span').text('Show More');
$target.children('ul').addClass('active');
}
sgg_update_terms(terms, target);
this.value = '';
return false;
}
}).data('ui-autocomplete')._renderItem = function (ul, item) {
if (item.value === 'false') {
return $('<li class="ui-state-disabled">' + item.label + '</li>').appendTo(ul);
} else {
return $('<li>').append(item.label).appendTo(ul);
}
};
});
/** Remove Term */
$(document).on('click', '.sgg-autocomplete-terms .remove-term', function (e) {
e.preventDefault();
let termValue = $(this).data('value');
let target = $(this).data('target');
let terms = sgg_get_terms(target);
if (termValue) {
terms = terms.filter(el => el.value != termValue)
sgg_update_terms(terms, target);
}
});
/** Form Actions */
$('#change-indexnow-key').on('mouseup', function () {
$('input[name="change_indexnow_key"]').val('change');
});
$('#clear-sitemap-cache').on('mouseup', function () {
$('input[name="clear_cache"]').val('clear');
});
$importSettings.on('mouseup', function () {
$importSettingsInput.val('import');
});
$importSettings.on('click', function (e) {
if ($importSettingsInput.val().trim() !== '' && !confirm('Your current Settings will be replaced with importing values. Would you like to continue?')) {
e.preventDefault();
$importSettingsInput.val('');
}
});
$('#sgg-indexnow').on('mouseup', function () {
$('input[name="sgg-indexnow"]').val('check');
});
$('#sgg-flush-rewrite-rules').on('mouseup', function () {
$('input[name="sgg-flush-rewrite-rules"]').val('check');
});
$('#sgg-clear-cache').on('mouseup', function () {
$('input[name="sgg-clear-cache"]').val('check');
});
$('#youtube-check-api-key').on('mouseup', function () {
$('input[name="youtube_check_api_key"]').val('check');
});
$('#vimeo-check-api-key').on('mouseup', function () {
$('input[name="vimeo_check_api_key"]').val('check');
});
$('#clear-video-api-cache').on('mouseup', function () {
$('input[name="clear_video_api_cache"]').val('clear');
});
function sgg_get_terms(target) {
let selector = $(`#${target}`)
return JSON.parse(!selector.val() ? '[]' : selector.val());
}
function sgg_update_terms(terms, target) {
$(`#${target}`).val(JSON.stringify(terms));
sgg_render_terms(terms, target);
}
function sgg_render_terms(terms, target) {
let $target = $(`#${target}`);
let $expand = $target.siblings('.expand');
let $tbody = $expand.find('.sgg-autocomplete-terms');
if (terms.length < 1) {
$expand.find('.grim-table').attr('data-count', 0)
} else {
$expand.find('.grim-table').attr('data-count', terms.length);
}
$tbody.html('');
terms.forEach((term, index) => {
const hiddenClass = index >= 5 ? 'grim-term-hidden' : '';
$tbody.append(`
<tr class="${hiddenClass}">
<td>${term.label}</td>
<td>
<a href="#" class="remove-term" data-value="${term.value}" data-target="${target}">
<i class="grim-icon-trash"></i>
</a>
</td>
</tr>
`);
});
$expand.find('.grim-expand-toggle').toggle(terms.length > 5);
updateAllTabCounts()
}
function updateAllTabCounts() {
$('.grim-section').each(function() {
let $section = $(this);
$section.find('.grim-exclude-tab').each(function() {
let tabId = $(this).data('tab');
let $panel = $section.find('#' + tabId);
let count = $panel.find('.grim-table').attr('data-count') || 0;
$(this).find('.grim-term-count').text(count);
});
let $includePanel = $section.find('#others, #google-others');
if ($includePanel.length) {
let count = $includePanel.find('.grim-table').attr('data-count') || 0;
$section.find('.grim-term-count').text(count);
}
});
}
function sgg_dependency(elements, checked) {
$(elements).attr('disabled', checked).toggleClass('dependency-disabled', checked);
}
$(document).on('click', '.grim-select__trigger', function () {
let $select = $(this).closest('.grim-select');
$('.grim-select').not($select).removeClass('open');
$select.toggleClass('open');
});
$(document).on('click', '.grim-select .grim-option', function () {
let $option = $(this);
let $select = $option.closest('.grim-select');
let value = $option.data('value');
let text = $option.text();
let $hiddenSelect = $select.next('select');
$select.find('.grim-option').removeClass('selected');
$option.addClass('selected');
$select.find('.grim-select__trigger span').text(text);
if ($hiddenSelect.length) {
$hiddenSelect.val(value).trigger('change');
}
$select.removeClass('open');
});
$('.grim-exclude-tab-nav .grim-exclude-tab').on('click', function() {
let tabId = $(this).data('tab');
let $container = $(this).closest('.grim-exclude-tab-nav');
$container.find('.grim-exclude-tab').removeClass('grim-exclude-tab--active');
$(this).addClass('grim-exclude-tab--active');
$container.find('.grim-exclude-tab-panel').removeClass('grim-exclude-tab-panel--active');
$container.find('#' + tabId).addClass('grim-exclude-tab-panel--active');
});
$(document).on('click', function (e) {
if (!$(e.target).closest('.grim-select').length) {
$('.grim-select').removeClass('open');
}
});
$('#grim-import-file').on('change', function() {
let fileName = this.files.length ? this.files[0].name : 'No file chosen';
$('#grim-file-name').text(fileName);
});
$(".grim-btn-copied").on("click", function() {
const targetId = $(this).data("target");
const text = $("#" + targetId).text()
.replace(/\t+/g, " ")
.replace(/\s*\n\s*/g, "\n")
.trim();
const $btn = $(this);
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(() => {
showTooltip($btn);
});
} else {
let $temp = $("<textarea>");
$("body").append($temp);
$temp.val(text).select();
document.execCommand("copy");
$temp.remove();
showTooltip($btn);
}
});
function showTooltip($btn) {
$btn.addClass("grim-show-tooltip");
setTimeout(() => {
$btn.removeClass("grim-show-tooltip");
}, 1500);
}
/** Settings Search Functionality */
const $searchInput = $('#grim-settings-search-input');
const $searchResults = $('#grim-search-results');
const $searchResultsList = $searchResults.find('.grim-search-results-list');
function searchSettings(query) {
if (!query || query.length < 2) {
$searchResults.hide();
return;
}
const results = grimData.settingsArray.filter(setting => {
const searchText = query.toLowerCase();
const labelMatch = setting.label.toLowerCase().includes(searchText);
const idMatch = setting.id.toLowerCase().includes(searchText);
const tagsMatch = setting.tags && setting.tags.toLowerCase().includes(searchText);
return labelMatch || idMatch || tagsMatch;
});
displaySearchResults(results);
}
function displaySearchResults(results) {
$searchResultsList.empty();
if (results.length === 0) {
$searchResultsList.append(`<div class="grim-search-no-results">${grimData.noSettingsFound}</div>`);
} else {
results.forEach(setting => {
const $resultItem = $(`
<div class="grim-search-result-item" data-setting-id="${setting.id}" data-tab="${setting.tab}">
<div class="grim-search-result-label">${setting.label}</div>
<div class="grim-search-result-tab">${getTabName(setting.tab)}</div>
</div>
`);
$searchResultsList.append($resultItem);
});
}
$searchResults.show();
}
function getTabName(tabId) {
const tabNames = {
'general': 'General',
'google-news': 'Google News',
'image-sitemap': 'Image Sitemap',
'video-sitemap': 'Video Sitemap',
'advanced': 'Advanced'
};
return tabNames[tabId] || tabId;
}
$searchInput.on('input', function() {
const query = $(this).val().trim();
searchSettings(query);
});
$searchResultsList.on('click', '.grim-search-result-item', function() {
const settingId = $(this).data('setting-id');
const tabId = $(this).data('tab');
switchToTab(tabId);
setTimeout(() => {
scrollToSetting(settingId);
}, 300);
$searchResults.hide();
});
function switchToTab(tabId) {
const $targetTab = $(`.nav-tab-wrapper a[data-id="${tabId}"]`);
if ($targetTab.length) {
$tabsList.removeClass('nav-tab-active');
$targetTab.addClass('nav-tab-active');
$contentList.hide();
const targetIndex = $targetTab.index();
$contentList.eq(targetIndex).show();
sessionStorage.setItem('sggActiveTab', tabId);
}
}
function scrollToSetting(settingId) {
const setting = grimData.settingsArray.find(s => s.id === settingId);
if (setting) {
let $element = $(`[data-search-id="${settingId}"]`)
if ($element.length) {
const $container = $element;
if ($container.length) {
const elementTop = $container.offset().top;
let scrollTop = elementTop - 280;
$('html, body').animate({
scrollTop: scrollTop
}, 500);
$element.addClass('grim-search-highlight');
setTimeout(() => {
$element.removeClass('grim-search-highlight');
}, 1600);
}
}
}
}
$(document).on('click', function(e) {
if (!$(e.target).closest('.grim-settings-search').length) {
$searchResults.hide();
}
});
$searchInput.on('keydown', function(e) {
if (e.key === 'Escape') {
$searchResults.hide();
$(this).val('');
}
});
let isSearchOpen = false;
$('.grim-search-action-btn').on('click', function () {
const $btn = $(this);
$btn.css({
transition: 'opacity 0.2s ease',
opacity: 0
});
setTimeout(() => {
$btn.hide();
}, 200);
isSearchOpen = true;
$('.grim-settings-search').fadeIn(200);
});
$('.grim-settings-search-cancel').on('click', function () {
const $btn = $('.grim-search-action-btn');
$btn.css({
transition: 'opacity 0.2s ease',
opacity: 1
});
setTimeout(() => {
$btn.show();
}, 200);
isSearchOpen = false;
$('.grim-settings-search').fadeOut(200);
$searchInput.val('');
});
const $nav = $('.grim-nav');
let grimDynamicNotice = $('.grim-dynamic-notice').length || 0;
let grimNotice = $('.grim-container .notice.is-dismissible');
let grimNoticeLength = $(grimNotice).length || 0;
let grimNoticeHeight = 0;
grimNotice.each(function() {
grimNoticeHeight = $(this).outerHeight();
});
const getScrollThreshold = () => {
return 20 + (grimDynamicNotice * 160) + (grimNoticeLength * grimNoticeHeight);
};
let scrollThreshold = getScrollThreshold();
$('.sgg-notice').on('click', () => {
grimDynamicNotice--;
scrollThreshold = getScrollThreshold();
});
$('.notice-dismiss').on('click', () => {
grimNoticeLength--;
scrollThreshold = getScrollThreshold();
});
let isSticky = false;
function handleScroll() {
const scrollTop = $(window).scrollTop();
if (scrollTop > scrollThreshold && !isSticky) {
$nav.removeClass('sticky-removing');
$nav.addClass('sticky');
isSticky = true;
updateViewForStickyState();
} else if (scrollTop <= scrollThreshold && isSticky) {
$nav.addClass('sticky-removing');
setTimeout(() => {
$nav.removeClass('sticky sticky-removing');
isSticky = false;
updateViewForStickyState();
}, );
}
}
function updateViewForStickyState() {
const $search = $('.grim-settings-search');
const $searchBtn = $('.grim-search-action-btn');
if ( isSearchOpen && !isSticky ) {
$search.show();
$searchBtn.hide();
} else if (isSearchOpen && isSticky) {
$searchBtn.hide();
$search.show();
}
}
$(window).on('scroll', handleScroll);
handleScroll();
});

View File

@@ -0,0 +1,80 @@
"use strict";
jQuery(document).ready(function($) {
const stepMenus = $('[class^="wizard-step-menu"]');
const formSteps = $('[class^="wizard-form-step-"]');
const formSubmitBtn = $('.wizard-btn');
const formBackBtn = $('.wizard-back-btn');
let currentStep = 0;
updateStep(currentStep);
$(document).on('change', '.sitemap-cache-toggle input', function() {
$('.sitemap-cache').attr('disabled', !$(this).is(':checked'));
});
formSubmitBtn.on("click", function(event) {
event.preventDefault();
if (currentStep < formSteps.length - 1) {
currentStep++;
updateStep(currentStep);
} else {
$('.wizard-form-btn-wrapper').addClass('loading');
let data = new FormData();
data.append('action', 'save_wizard_settings');
data.append('nonce', sggWizard.nonce);
$('#wizard-form').serializeArray().forEach(function(item) {
data.append(item.name, item.value);
});
$.ajax({
url: sggWizard.ajax_url,
type: 'POST',
data: data,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
window.location.href = response.redirect;
} else {
console.log(response);
}
$('.wizard-form-btn-wrapper').removeClass('loading');
}
});
}
});
formBackBtn.on("click", function(event) {
event.preventDefault();
if (currentStep > 0) {
currentStep--;
updateStep(currentStep);
}
});
function updateStep(stepIndex) {
formSteps.removeClass('active');
formSteps.eq(stepIndex).addClass('active');
stepMenus.removeClass('active');
stepMenus.eq(stepIndex).addClass('active');
stepMenus.slice(0, stepIndex).addClass('completed');
stepMenus.slice(stepIndex).removeClass('completed');
if (stepIndex === 0) {
formBackBtn.removeClass('active');
} else {
formBackBtn.addClass('active');
}
if (stepIndex === formSteps.length - 1) {
formSubmitBtn.removeClass('right-icon').find('span').text(sggWizard.finish);
}
}
});

View File

@@ -0,0 +1,174 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class Cache extends Controller {
private static $max_chunk_size = 500000;
private static $prefix = 'sgg_cache_';
public static $sitemaps = array(
'sitemap',
'inner-sitemap',
'google-news',
'image-sitemap',
'video-sitemap',
);
public $sitemap;
public $inner_sitemap;
public $current_page;
public function __construct( $sitemap = 'sitemap', $inner_sitemap = null, $current_page = null ) {
$this->sitemap = $this->get_multilingual_sitemap_name( $sitemap );
$this->inner_sitemap = $inner_sitemap;
$this->current_page = $current_page ?? '';
}
public function set( $urls ) {
$expiration = self::get_expiration( $this->get_settings() );
$option_name = self::$prefix . $this->sitemap;
if ( $this->inner_sitemap ) {
$cached_urls = get_transient( $option_name );
if ( empty( $cached_urls ) ) {
$cached_urls = array();
}
if ( ! empty( $urls[ $this->inner_sitemap ] ) ) {
$cached_urls[ $this->inner_sitemap . $this->current_page ] = $urls[ $this->inner_sitemap ];
}
$urls = $cached_urls;
}
// Only apply splitting for Media Sitemaps.
if ( strpos( $this->sitemap, 'media-' ) === 0 ) {
$serialized = maybe_serialize( $urls );
if ( strlen( $serialized ) > self::$max_chunk_size ) {
$chunks = str_split( $serialized, self::$max_chunk_size );
foreach ( $chunks as $i => $chunk ) {
set_transient( $option_name . '_chunk_' . $i, $chunk, $expiration );
}
set_transient( $option_name . '_chunks', count( $chunks ), $expiration );
set_transient( $option_name . '_time', time(), $expiration );
return;
}
}
set_transient( $option_name, $urls, $expiration );
set_transient( $option_name . '_time', time(), $expiration );
}
public function get() {
$option_name = self::$prefix . $this->sitemap;
// Check if the data was saved in chunks.
$chunks_count = get_transient( $option_name . '_chunks' );
if ( false !== $chunks_count ) {
$serialized = '';
for ( $i = 0; $i < $chunks_count; $i ++ ) {
$chunk = get_transient( $option_name . '_chunk_' . $i );
if ( false === $chunk ) {
return null;
}
$serialized .= $chunk;
}
$urls = maybe_unserialize( $serialized );
} else {
$urls = get_transient( $option_name );
}
if ( $this->inner_sitemap ) {
if ( empty( $urls[ $this->inner_sitemap . $this->current_page ] ) ) {
return null;
}
return array(
$this->inner_sitemap => $urls[ $this->inner_sitemap . $this->current_page ],
);
}
return $urls;
}
public static function get_time( $sitemap ) {
return get_transient( self::$prefix . $sitemap . '_time' );
}
public static function get_time_formatted( $sitemap ) {
$time = self::get_time( $sitemap );
return $time
// translators: %s is Cached Time
? sprintf( __( '%s ago', 'xml-sitemap-generator-for-google' ), human_time_diff( $time, time() ) )
: __( 'No Cache', 'xml-sitemap-generator-for-google' );
}
public static function delete( $sitemap ): void {
$option_name = self::$prefix . $sitemap;
delete_transient( $option_name );
delete_transient( $option_name . '_time' );
// Delete chunks if they exist.
$chunks_count = get_transient( $option_name . '_chunks' );
if ( false !== $chunks_count ) {
for ( $i = 0; $i < $chunks_count; $i ++ ) {
delete_transient( $option_name . '_chunk_' . $i );
}
}
delete_transient( $option_name . '_chunks' );
}
public static function clear(): void {
foreach ( self::$sitemaps as $sitemap ) {
self::delete( $sitemap );
}
}
public static function maybe_clear( $expiration ): void {
foreach ( self::$sitemaps as $sitemap ) {
if ( $expiration < time() - self::get_time( $sitemap ) ) {
self::delete( $sitemap );
}
}
}
public static function get_expiration( $settings ) {
return intval( $settings->cache_timeout ?? 24 ) * intval( $settings->cache_timeout_period ?? 3600 );
}
public function get_multilingual_sitemap_name( $sitemap ) {
$suffix = '';
if ( function_exists( 'pll_current_language' ) ) {
$suffix = pll_current_language();
}
if ( function_exists( 'trp_get_languages' ) ) {
$trp_settings = get_option( 'trp_settings' );
$suffix = $trp_settings['default-language'] ?? null;
}
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
$suffix = apply_filters( 'wpml_current_language', null );
}
if ( ! empty( $suffix ) ) {
$sitemap = "{$sitemap}_{$suffix}";
}
return $sitemap;
}
}

View File

@@ -0,0 +1,503 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
use SGG_PRO\Classes\Video_Sitemap;
use SGG_PRO\Classes\Video_Data_Cache;
class Dashboard extends Controller {
/**
* Dashboard constructor.
*/
public function __construct() {
add_action( 'admin_init', array( $this, 'register_settings' ) );
add_action( 'admin_menu', array( $this, 'admin_menu_pages' ) );
add_filter( 'plugin_action_links_' . GRIM_SG_BASENAME, array( $this, 'plugin_action_links' ) );
add_filter( 'plugin_row_meta', array( $this, 'plugin_meta_links' ), 10, 2 );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'admin_print_footer_scripts', array( $this, 'add_plugin_logo_script' ) );
}
/**
* Menu
*/
public function admin_menu_pages() {
add_options_page(
esc_html__( 'Google XML Sitemaps Generator Settings', 'xml-sitemap-generator-for-google' ),
esc_html__( 'XML Sitemaps', 'xml-sitemap-generator-for-google' ),
'manage_options',
self::$slug,
array( $this, 'render_settings_page' )
);
}
/**
* Enqueue admin styles and scripts for plugin
*/
public function admin_enqueue_scripts( $hook ) {
wp_register_style(
'sgg-rate-banner',
GRIM_SG_URL . 'assets/css/rate-banner.min.css',
array(),
GRIM_SG_VERSION
);
wp_register_style(
'sgg-icons',
GRIM_SG_URL . 'assets/fonts/icons/style.css',
array(),
GRIM_SG_VERSION
);
if ( 'settings_page_xml-sitemap-generator-for-google' === $hook ) {
wp_enqueue_style( 'sgg-fonts', GRIM_SG_URL . 'assets/fonts/albert_sans/fonts.css', array(), GRIM_SG_VERSION );
wp_enqueue_style( 'sgg-icons', GRIM_SG_URL . 'assets/fonts/icons/style.css', array(), GRIM_SG_VERSION );
wp_enqueue_style( 'sgg-styles', GRIM_SG_URL . 'assets/css/styles.min.css', array( 'sgg-fonts' ), GRIM_SG_VERSION );
wp_enqueue_script( 'jquery-ui', GRIM_SG_URL . 'assets/js/jquery-ui.min.js', array( 'jquery' ), GRIM_SG_VERSION, true );
wp_enqueue_script( 'sgg-scripts', GRIM_SG_URL . 'assets/js/scripts.js', array( 'jquery' ), GRIM_SG_VERSION, true );
if ( function_exists( 'xml_sitemap_generate_settings' ) ) {
$settings_array = xml_sitemap_generate_settings() ?? array();
wp_localize_script(
'sgg-scripts',
'grimData',
array(
'settingsArray' => $settings_array,
'noSettingsFound' => esc_html__( 'Settings not found', 'xml-sitemap-generator-for-google' ),
'NoUrls' => esc_html__( 'No URLs added yet!', 'xml-sitemap-generator-for-google' ),
)
);
}
wp_localize_script(
'sgg-scripts',
'sgg',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
)
);
}
}
/**
* Settings page
*/
public function render_settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$this->save_settings();
self::render(
'settings.php',
array(
'settings' => $this->get_settings(),
'cpt' => $this->get_cpt( 'objects' ),
'taxonomies' => $this->get_taxonomy_types( 'objects' ),
)
);
}
/**
* Register Settings
*/
public function register_settings() {
register_setting( self::$slug, self::$slug );
}
/**
* Save Settings
*/
public function save_settings() {
if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ?? '' ) || ! isset( $_POST['save_settings'] ) ) {
return;
}
if ( ! isset( $_POST['sgg_settings_nonce'] ) || ! wp_verify_nonce( $_POST['sgg_settings_nonce'], GRIM_SG_BASENAME . '-settings' ) ) {
return;
}
// Run Tools Actions
if ( Tools::run_tools_actions( $_POST ) ) {
return;
}
// Change IndexNow API Key
if ( ! empty( $_POST['change_indexnow_key'] ) ) {
IndexNow::delete_api_key();
add_settings_error(
self::$slug,
'indexnow_api_key',
esc_html__( 'IndexNow API Key changed successfully.', 'xml-sitemap-generator-for-google' ),
'success'
);
return;
}
// Clear Media Sitemap Cache on every save
if ( empty( $_POST['disable_media_sitemap_cache'] ) ) {
MediaSitemap::delete_all_cache();
}
// Clear Sitemaps Cache
if ( ! empty( $_POST['clear_cache'] ) ) {
Cache::clear();
add_settings_error(
self::$slug,
'sitemap_cache',
esc_html__( 'Sitemaps Cache cleared.', 'xml-sitemap-generator-for-google' ),
'success'
);
return;
}
// Import Settings
if ( ! empty( $_POST['import_settings'] ) ) {
ImportExport::import_settings();
return;
}
// Clear Video Data Cache
if ( ! empty( $_POST['clear_video_api_cache'] ) && is_callable( 'SGG_PRO\Classes\Video_Data_Cache::delete' ) ) {
Video_Data_Cache::delete();
add_settings_error(
self::$slug,
'video_api_cache',
esc_html__( 'Video API Data Cache cleared.', 'xml-sitemap-generator-for-google' ),
'success'
);
return;
}
$settings = new Settings();
$saved_settings = $this->get_settings();
// Check YouTube API Key
if ( ( ! empty( $_POST['youtube_check_api_key'] ) || $saved_settings->youtube_api_key !== $_POST['youtube_api_key'] )
&& ! empty( $_POST['youtube_api_key'] ) && is_callable( 'SGG_PRO\Classes\Video_Sitemap::request_youtube_data' ) ) {
$youtube_data = Video_Sitemap::request_youtube_data( 'dQw4w9WgXcQ', sanitize_text_field( $_POST['youtube_api_key'] ) );
if ( ! empty( $youtube_data ) && is_array( $youtube_data ) ) {
add_settings_error( self::$slug, 'youtube_api_key_success', esc_html__( 'YouTube API key passed the check successfully.', 'xml-sitemap-generator-for-google' ), 'success' );
} else {
add_settings_error( self::$slug, 'youtube_api_key_error', "YouTube API: $youtube_data" );
}
if ( ! empty( $_POST['youtube_check_api_key'] ) ) {
return;
}
}
// Check Vimeo API Key
if ( ( ! empty( $_POST['vimeo_check_api_key'] ) || $saved_settings->vimeo_api_key !== $_POST['vimeo_api_key'] )
&& ! empty( $_POST['vimeo_api_key'] ) && is_callable( 'SGG_PRO\Classes\Video_Sitemap::request_vimeo_data' ) ) {
$vimeo_data = Video_Sitemap::request_vimeo_data( '22439234', sanitize_text_field( $_POST['vimeo_api_key'] ) );
if ( ! empty( $vimeo_data ) && is_array( $vimeo_data ) ) {
add_settings_error( self::$slug, 'vimeo_api_key_success', esc_html__( 'Vimeo Access Token passed the check successfully.', 'xml-sitemap-generator-for-google' ), 'success' );
} else {
add_settings_error( self::$slug, 'vimeo_api_key_error', "Vimeo API: $vimeo_data" );
}
if ( ! empty( $_POST['vimeo_check_api_key'] ) ) {
return;
}
}
// Change Cron Job if Runtime is changed
if ( ! isset( $_POST['enable_cronjob'] ) || ! $_POST['enable_cronjob'] || ( ! empty( $_POST['cronjob_runtime'] ) && $saved_settings->cronjob_runtime !== $_POST['cronjob_runtime'] ) ) {
wp_clear_scheduled_hook( 'xml_sitemap_cronjob' );
}
$settings->enable_sitemap = sanitize_text_field( $_POST['enable_sitemap'] ?? 0 );
$settings->sitemap_url = sanitize_text_field( $_POST['sitemap_url'] ?? $settings->sitemap_url );
$settings->links_per_page = sanitize_text_field( $_POST['links_per_page'] ?? $settings->links_per_page );
$settings->html_sitemap_url = sanitize_text_field( $_POST['html_sitemap_url'] ?? $settings->html_sitemap_url );
$settings->enable_html_sitemap = sanitize_text_field( $_POST['enable_html_sitemap'] ?? 0 );
$settings->sitemap_to_robots = sanitize_text_field( $_POST['sitemap_to_robots'] ?? 0 );
$settings->enable_indexnow = sanitize_text_field( $_POST['enable_indexnow'] ?? 0 );
$settings->sitemap_view = sanitize_text_field( $_POST['sitemap_view'] ?? '' );
$settings->exclude_posts = apply_filters( 'sanitize_post_array', $_POST['exclude_posts'] ?? '' );
$settings->exclude_terms = apply_filters( 'sanitize_post_array', $_POST['exclude_terms'] ?? '' );
$settings->include_only_terms = apply_filters( 'sanitize_post_array', $_POST['include_only_terms'] ?? '' );
$settings->posts_priority = sanitize_text_field( $_POST['posts_priority'] ?? '' );
$settings->enable_google_news = sanitize_text_field( $_POST['enable_google_news'] ?? 0 );
$settings->google_news_old_posts = sanitize_text_field( $_POST['google_news_old_posts'] ?? 0 );
$settings->google_news_name = sanitize_text_field( $_POST['google_news_name'] ?? '' );
$settings->google_news_url = sanitize_text_field( $_POST['google_news_url'] ?? $settings->google_news_url );
$settings->google_news_keywords = sanitize_text_field( $_POST['google_news_keywords'] ?? '' );
$settings->google_news_stocks = sanitize_text_field( $_POST['google_news_stocks'] ?? 0 );
$settings->google_news_exclude = apply_filters( 'sanitize_post_array', $_POST['google_news_exclude'] ?? '' );
$settings->google_news_exclude_terms = apply_filters( 'sanitize_post_array', $_POST['google_news_exclude_terms'] ?? '' );
$settings->google_news_include_only_terms = apply_filters( 'sanitize_post_array', $_POST['google_news_include_only_terms'] ?? '' );
$settings->enable_image_sitemap = sanitize_text_field( $_POST['enable_image_sitemap'] ?? 0 );
$settings->enable_video_sitemap = sanitize_text_field( $_POST['enable_video_sitemap'] ?? 0 );
$settings->image_sitemap_url = sanitize_text_field( $_POST['image_sitemap_url'] ?? $settings->image_sitemap_url );
$settings->video_sitemap_url = sanitize_text_field( $_POST['video_sitemap_url'] ?? $settings->video_sitemap_url );
$settings->hide_image_previews = sanitize_text_field( $_POST['hide_image_previews'] ?? 0 );
$settings->hide_image_sitemap_xsl = sanitize_text_field( $_POST['hide_image_sitemap_xsl'] ?? 0 );
$settings->hide_video_sitemap_xsl = sanitize_text_field( $_POST['hide_video_sitemap_xsl'] ?? 0 );
$settings->image_mime_types = apply_filters( 'sanitize_post_array', $_POST['image_mime_types'] ?? $settings->image_mime_types );
$settings->youtube_api_key = sanitize_text_field( $_POST['youtube_api_key'] ?? $settings->youtube_api_key );
$settings->vimeo_api_key = sanitize_text_field( $_POST['vimeo_api_key'] ?? $settings->vimeo_api_key );
$settings->exclude_broken_images = sanitize_text_field( $_POST['exclude_broken_images'] ?? 0 );
$settings->include_featured_images = sanitize_text_field( $_POST['include_featured_images'] ?? 0 );
$settings->include_woo_gallery = sanitize_text_field( $_POST['include_woo_gallery'] ?? 0 );
$settings->enable_cache = sanitize_text_field( $_POST['enable_cache'] ?? 0 );
$settings->cache_timeout = sanitize_text_field( $_POST['cache_timeout'] ?? $settings->cache_timeout );
$settings->cache_timeout_period = sanitize_text_field( $_POST['cache_timeout_period'] ?? $settings->cache_timeout_period );
$settings->clear_cache_on_save_post = sanitize_text_field( $_POST['clear_cache_on_save_post'] ?? 0 );
$settings->enable_video_api_cache = sanitize_text_field( $_POST['enable_video_api_cache'] ?? 0 );
$settings->disable_media_sitemap_cache = sanitize_text_field( $_POST['disable_media_sitemap_cache'] ?? 0 );
$settings->minimize_sitemap = sanitize_text_field( $_POST['minimize_sitemap'] ?? 0 );
$settings->colors = apply_filters( 'sanitize_post_array', $_POST['colors'] ?? $settings->colors );
$settings->hide_branding = sanitize_text_field( $_POST['hide_branding'] ?? 0 );
$settings->enable_cronjob = sanitize_text_field( $_POST['enable_cronjob'] ?? 0 );
$settings->cronjob_runtime = sanitize_text_field( $_POST['cronjob_runtime'] ?? $settings->cronjob_runtime );
$settings->home = $settings->get_row_value( 'home' );
$settings->page = $settings->get_row_value( 'page' );
$settings->post = $settings->get_row_value( 'post' );
$settings->archive = $settings->get_row_value( 'archive' );
$settings->archive_older = $settings->get_row_value( 'archive_older' );
$settings->authors = $settings->get_row_value( 'authors' );
$settings->media = $settings->get_row_value( 'media' );
foreach ( $this->get_cpt() as $cpt ) {
$settings->cpt[ $cpt ] = $settings->get_row_value( $cpt );
}
foreach ( $this->get_taxonomy_types() as $taxonomy_type ) {
$settings->taxonomies[ $taxonomy_type ] = $settings->get_row_value( $taxonomy_type );
}
$custom_sitemap_urls = apply_filters( 'sanitize_post_array', $_POST['custom_sitemap_urls'] ?? array() );
$custom_sitemap_lastmods = apply_filters( 'sanitize_post_array', $_POST['custom_sitemap_lastmods'] ?? array() );
foreach ( $custom_sitemap_urls as $key => $value ) {
$custom_sitemap = array(
'url' => $value,
'lastmod' => $custom_sitemap_lastmods[ $key ],
);
$settings->custom_sitemaps[] = $custom_sitemap;
}
$additional_urls = apply_filters( 'sanitize_post_array', $_POST['additional_urls'] ?? array() );
$additional_priorities = apply_filters( 'sanitize_post_array', $_POST['additional_priorities'] ?? array() );
$additional_frequencies = apply_filters( 'sanitize_post_array', $_POST['additional_frequencies'] ?? array() );
$additional_lastmods = apply_filters( 'sanitize_post_array', $_POST['additional_lastmods'] ?? array() );
foreach ( $additional_urls as $key => $value ) {
$page = array(
'url' => $value,
'priority' => $additional_priorities[ $key ],
'frequency' => $additional_frequencies[ $key ],
'lastmod' => $additional_lastmods[ $key ],
);
$settings->additional_pages[] = $page;
}
update_option( self::$slug, $settings );
$new_cache_expires = Cache::get_expiration( $settings );
if ( Cache::get_expiration( $saved_settings ) !== $new_cache_expires ) {
Cache::maybe_clear( $new_cache_expires );
}
if ( ( $settings->sitemap_view !== $saved_settings->sitemap_view ) || ( $settings->links_per_page !== $saved_settings->links_per_page ) ) {
Cache::clear();
flush_rewrite_rules();
}
add_settings_error(
self::$slug,
'sitemap_settings',
esc_html__( 'Changes saved!', 'xml-sitemap-generator-for-google' ),
'success'
);
flush_rewrite_rules();
}
/**
* Render Sitemap Post Row
* @param $title
* @param $option
* @param $data
*/
public static function render_post_row( $title, $option, $data ) {
self::render(
'fields/post-row.php',
array(
'title' => $title,
'option' => $option,
'data' => $data,
)
);
}
/**
* Render Priority Selectbox
* @param $name
* @param $value
*/
public static function render_priority_field( $name, $value ) {
self::render(
'fields/priority.php',
array(
'name' => $name,
'value' => $value,
)
);
}
/**
* Render Frequency Selectbox
* @param $name
* @param $value
*/
public static function render_frequency_field( $name, $value ) {
self::render(
'fields/frequency.php',
array(
'name' => $name,
'value' => $value,
)
);
}
/**
* Render Google News Selectbox
* @param $title
* @param $name
* @param $value
*/
public static function render_content_field( $title, $name, $value, $class = '' ) {
self::render(
'fields/content.php',
array(
'title' => $title,
'name' => $name,
'value' => $value,
'class' => $class,
)
);
}
/**
* Render Template
* @param $template_name
* @param $args
*/
public static function render( $template_name, $args = array() ) {
global $wp_version;
if ( version_compare( $wp_version, '5.5.0', '<' ) ) {
set_query_var( 'args', $args );
}
load_template( GRIM_SG_PATH . "/templates/{$template_name}", false, $args );
}
/**
* Setting Link
*
* @param $links
* @return mixed
*/
public function plugin_action_links( $links ) {
$settings_link = sprintf(
'<a href="%1$s">%2$s</a>',
admin_url( 'options-general.php?page=' . self::$slug ),
esc_html__( 'Settings', 'xml-sitemap-generator-for-google' )
);
$docs_link = sprintf(
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
esc_url( 'https://wpgrim.com/docs/google-xml-sitemaps-generator/general/xml-sitemap/' ),
esc_html__( 'Docs', 'xml-sitemap-generator-for-google' )
);
if ( ! sgg_pro_enabled() ) {
$pro_link = sprintf(
'<a href="%1$s" style="font-weight: 600; color: #ff7113;" target="_blank">%2$s</a>',
sgg_get_pro_url( 'plugin-action-link' ),
esc_html__( 'Get Pro Version', 'xml-sitemap-generator-for-google' )
);
$links = array_merge( array( $pro_link, $settings_link, $docs_link ), $links );
} else {
$links = array_merge( array( $settings_link, $docs_link ), $links );
}
return $links;
}
/**
* Meta Links
*
* @param $links
* @return mixed
*/
public function plugin_meta_links( $links, $file ) {
if ( GRIM_SG_BASENAME === $file ) {
$links[] = '<a href="' . esc_url( sgg_get_support_url() ) . '" target="_blank">' . __( 'Support', 'xml-sitemap-generator-for-google' ) . '</a>';
$links[] = '<a href="' . esc_url( sgg_get_review_url() ) . '" target="_blank">' . __( 'Rate ★★★★★', 'xml-sitemap-generator-for-google' ) . '</a>';
}
return $links;
}
/**
* Add plugin logo script to plugins page
*/
public function add_plugin_logo_script() {
global $pagenow;
// Only add script on plugins page
if ( 'plugins.php' !== $pagenow ) {
return;
}
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// Find the plugin row for XML Sitemap Generator
const pluginRow = document.querySelector('tr[data-slug="xml-sitemap-generator-for-google"]');
if (pluginRow) {
const pluginTitle = pluginRow.querySelector('.plugin-title strong');
if (pluginTitle) {
// Create logo element
const logo = document.createElement('img');
logo.src = '<?php echo esc_url( GRIM_SG_URL . 'assets/images/sgg-logo.svg' ); ?>';
logo.alt = 'XML Sitemap Generator Logo';
logo.style.width = '20px';
logo.style.height = '20px';
logo.style.paddingRight = '10px';
logo.style.verticalAlign = 'middle';
// Insert logo before the plugin title
pluginTitle.insertBefore(logo, pluginTitle.firstChild);
}
}
});
</script>
<?php
}
}

View File

@@ -0,0 +1,240 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class Frontend extends Controller {
private static $rules_option = 'grim_sg_rules';
private static $rules_version = '1.1';
/**
* Sitemap constructor.
*/
public function __construct() {
self::set_rewrite_hooks();
add_filter( 'query_vars', array( $this, 'register_query_vars' ), 1 );
add_action( 'parse_request', array( $this, 'render_sitemaps' ), 1 );
add_action( 'do_robots', array( $this, 'do_robots_link' ), 100 );
add_action( 'admin_init', array( $this, 'reset_rewrite_rules' ) );
}
/**
* Register Sitemap Query Variable
* @param $query_vars
* @return mixed
*/
public function register_query_vars( $query_vars ) {
$query_vars[] = 'sitemap_xsl';
$query_vars[] = 'sitemap_xml';
$query_vars[] = 'sitemap_html';
$query_vars[] = 'google_news';
$query_vars[] = 'image_sitemap';
$query_vars[] = 'video_sitemap';
$query_vars[] = 'inner_sitemap';
$query_vars[] = 'multilingual_sitemap';
$query_vars[] = 'page';
return $query_vars;
}
/**
* Template Redirect
*/
public function render_sitemaps( $wp ) {
global $wp_query;
$is_xsl_sitemap = ! empty( $wp->query_vars['sitemap_xsl'] );
$is_xml_sitemap = ! empty( $wp->query_vars['sitemap_xml'] );
$is_html_sitemap = ! empty( $wp->query_vars['sitemap_html'] );
$is_google_news = ! empty( $wp->query_vars['google_news'] );
$is_image_sitemap = ! empty( $wp->query_vars['image_sitemap'] );
$is_video_sitemap = ! empty( $wp->query_vars['video_sitemap'] );
$is_multilingual = ! empty( $wp->query_vars['multilingual_sitemap'] );
if ( $is_xsl_sitemap || $is_xml_sitemap || $is_html_sitemap || $is_google_news || $is_image_sitemap || $is_video_sitemap || $is_multilingual ) {
$wp_query->is_404 = false;
$wp_query->is_feed = true;
$inner_sitemap = $wp->query_vars['inner_sitemap'] ?? null;
$current_page = $wp->query_vars['page'] ?? null;
if ( ! empty( $inner_sitemap ) && empty( $current_page ) ) {
$current_page = 0;
}
if ( $is_xsl_sitemap ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
Sitemap::generate_sitemap_xsl( sanitize_text_field( $_GET['template'] ?? $wp->query_vars['sitemap_xsl'] ) );
} elseif ( $is_google_news ) {
( new GoogleNews() )->show_sitemap( GoogleNews::$template );
} elseif ( $is_image_sitemap || 'image' === $inner_sitemap ) {
( new ImageSitemap() )->show_sitemap( ImageSitemap::$template, true, $inner_sitemap, $current_page );
} elseif ( $is_video_sitemap || 'video' === $inner_sitemap ) {
( new VideoSitemap() )->show_sitemap( VideoSitemap::$template, true, $inner_sitemap, $current_page );
} elseif ( $is_multilingual ) {
( new MultilingualSitemap() )->show_sitemap( MultilingualSitemap::$template );
} else {
( new Sitemap() )->show_sitemap( 'sitemap', $is_xml_sitemap, $inner_sitemap, $current_page );
}
exit;
}
}
/**
* Add Sitemap Links to Robots
*/
public function do_robots_link() {
$settings = $this->get_settings();
$home_url = get_site_url();
if ( $settings->sitemap_to_robots ) {
echo "\nSitemap: {$home_url}/{$settings->sitemap_url}\n"; // phpcs:ignore
if ( $settings->enable_google_news ) {
echo "Sitemap: {$home_url}/{$settings->google_news_url}\n"; // phpcs:ignore
}
if ( empty( $settings->sitemap_view ) ) {
if ( $settings->enable_image_sitemap ) {
echo "Sitemap: {$home_url}/{$settings->image_sitemap_url}\n"; // phpcs:ignore
}
if ( $settings->enable_video_sitemap ) {
echo "Sitemap: {$home_url}/{$settings->video_sitemap_url}\n"; // phpcs:ignore
}
}
}
}
/**
* Add Custom Rewrite Rules
*
* @param $wp_rules
* @return array
*/
public static function add_rewrite_rules( $wp_rules ) {
$settings = get_option( self::$slug, new Settings() );
$stylesheet_url = str_replace( '.', '\.', apply_filters( 'sitemap_xsl_template_path', 'sitemap-stylesheet.xsl' ) ) . '$';
$sitemap_types = array( 'page', 'post', 'category', 'author', 'archive', 'media', 'additional', 'image', 'video' );
$custom_posts = ( new Controller() )->get_cpt();
$grim_sg_rules = array(
$stylesheet_url => 'index.php?sitemap_xsl=true',
);
if ( ! empty( $settings->enable_sitemap ) && ! apply_filters( 'sgg_disable_xml_sitemap', false ) ) {
$sitemap_url = str_replace( '.', '\.', $settings->sitemap_url ) . '$';
$grim_sg_rules[ $sitemap_url ] = 'index.php?sitemap_xml=true';
if ( ! empty( $settings->sitemap_view ) ) {
foreach ( $sitemap_types as $type ) {
$regex_pattern = in_array( $type, array( 'image', 'video' ) )
? "{$type}-sitemap([0-9]+)\.xml$"
: "{$type}-sitemap([0-9]+)?\.xml$";
$grim_sg_rules[ $regex_pattern ] = "index.php?sitemap_xml=true&inner_sitemap={$type}&page=\$matches[1]";
}
foreach ( $custom_posts as $cpt ) {
$grim_sg_rules[ "{$cpt}-sitemap([0-9]+)?\.xml$" ] = "index.php?sitemap_xml=true&inner_sitemap={$cpt}&page=\$matches[1]";
}
}
}
if ( sgg_pro_enabled() && $settings->enable_html_sitemap ) {
$html_sitemap_url = str_replace( '.', '\.', $settings->html_sitemap_url ) . '$';
$grim_sg_rules[ $html_sitemap_url ] = 'index.php?sitemap_html=true';
foreach ( $sitemap_types as $type ) {
$regex_pattern = in_array( $type, array( 'image', 'video' ) )
? "{$type}-sitemap([0-9]+)\.html$"
: "{$type}-sitemap([0-9]+)?\.html$";
$grim_sg_rules[ $regex_pattern ] = "index.php?sitemap_html=true&inner_sitemap={$type}&page=\$matches[1]";
}
foreach ( $custom_posts as $cpt ) {
$grim_sg_rules[ "{$cpt}-sitemap([0-9]+)?\.html$" ] = "index.php?sitemap_html=true&inner_sitemap={$cpt}&page=\$matches[1]";
}
}
if ( $settings->enable_google_news ) {
$google_news_url = str_replace( '.', '\.', $settings->google_news_url ) . '$';
$grim_sg_rules[ $google_news_url ] = 'index.php?google_news=true';
}
if ( $settings->enable_image_sitemap ) {
$image_sitemap_url = str_replace( '.', '\.', $settings->image_sitemap_url ) . '$';
$grim_sg_rules[ $image_sitemap_url ] = 'index.php?image_sitemap=true';
}
if ( $settings->enable_video_sitemap ) {
$video_sitemap_url = str_replace( '.', '\.', $settings->video_sitemap_url ) . '$';
$grim_sg_rules[ $video_sitemap_url ] = 'index.php?video_sitemap=true';
}
if ( sgg_is_multilingual() ) {
$languages = sgg_get_languages( true );
if ( ! empty( $languages ) ) {
global $wp_rewrite;
$lang_slug = $wp_rewrite->root . '^(' . implode( '|', $languages ) . ')?/?';
$lang_rules = array();
foreach ( $grim_sg_rules as $key => $rule ) {
$lang_rules[ $lang_slug . $key ] = preg_replace( '/matches\[1\]/', 'matches[2]', $rule );
}
$grim_sg_rules = $lang_rules;
}
$grim_sg_rules['multilingual-sitemap.xml'] = 'index.php?multilingual_sitemap=true';
}
if ( empty( $wp_rules ) ) {
return $grim_sg_rules;
}
return array_merge( $grim_sg_rules, $wp_rules );
}
/**
* Set Rewrite Hooks
*/
public static function set_rewrite_hooks() {
add_filter( 'option_rewrite_rules', array( self::class, 'add_rewrite_rules' ), 100, 1 );
}
/**
* Activate Rewrite Rules
*/
public static function activate_rewrite_rules() {
global $wp_rewrite;
$wp_rewrite->flush_rules( false );
update_option( self::$rules_option, self::$rules_version );
}
/**
* Run on Plugin Activate
*/
public static function activate_plugin() {
self::set_rewrite_hooks();
self::activate_rewrite_rules();
flush_rewrite_rules();
}
/**
* Run on Rules Version Updated
*/
public function reset_rewrite_rules() {
$rules_version = get_option( self::$rules_option, false );
if ( $rules_version !== self::$rules_version ) {
self::activate_plugin();
}
}
}

View File

@@ -0,0 +1,171 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\QueryBuilder;
class GoogleNews extends Sitemap {
public static $template = 'google-news';
private $blog_language = null;
/**
* Add URLS Callback function
*/
public function urlsCallback() {
return 'addNewsUrl';
}
/**
* Adding Google News Sitemap Headers
*/
public function extraSitemapHeader() {
return array( 'xmlns:news' => 'http://www.google.com/schemas/sitemap-news/0.9' );
}
/**
* Collect Sitemap URLs
*/
public function collect_urls( $template = 'sitemap', $inner_sitemap = null, $current_page = null ) {
$this->add_posts();
}
/**
* Add all Posts to Sitemap
*/
public function add_posts( $post_type = null, $current_page = null, $is_sitemap_index = false ) {
global $wpdb;
$front_page_id = get_option( 'page_on_front' );
$post_types = array( 'page', 'post' );
$exclude_post_ids = apply_filters( 'sgg_sitemap_exclude_post_ids', apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->google_news_exclude ?? '' ) );
$exclude_term_ids = apply_filters( 'sgg_sitemap_exclude_term_ids', apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->google_news_exclude_terms ?? '' ) );
$include_term_ids = apply_filters( 'sgg_sitemap_include_only_term_ids', apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->google_news_include_only_terms ?? '' ) );
if ( ! empty( $front_page_id ) ) {
$exclude_post_ids[] = $front_page_id;
}
foreach ( $post_types as $key => $post_type ) {
if ( isset( $this->settings->{$post_type}->google_news ) && ! $this->settings->{$post_type}->google_news ) {
unset( $post_types[ $key ] );
}
}
if ( sgg_pro_enabled() ) {
foreach ( $this->get_cpt() as $cpt ) {
if ( ! empty( $this->settings->cpt[ $cpt ] ) && ! empty( $this->settings->cpt[ $cpt ]->google_news ) ) {
$post_types[] = $cpt;
}
}
}
if ( empty( $post_types ) ) {
$post_types = array( 'post' );
}
$exclude_old_posts_sql = '';
if ( empty( $this->settings->google_news_old_posts ) ) {
$exclude_old_posts_sql = 'AND post_date_gmt >= DATE_SUB(NOW(), INTERVAL 48 HOUR)';
}
$exclude_posts_sql = '';
if ( ! empty( $exclude_post_ids ) ) {
$exclude_posts_sql = 'AND posts.ID NOT IN (' . implode( ',', array_unique( $exclude_post_ids ) ) . ')';
}
$terms_join_sql = '';
$terms_where_sql = '';
if ( ! empty( $include_term_ids ) ) {
$terms_join_sql = "INNER JOIN (
SELECT DISTINCT tr.object_id
FROM {$wpdb->term_relationships} tr
INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.term_id IN (" . implode( ',', array_unique( $include_term_ids ) ) . ')
) included_posts ON posts.ID = included_posts.object_id';
} elseif ( ! empty( $exclude_term_ids ) ) {
$terms_join_sql = "LEFT JOIN (
SELECT DISTINCT tr.object_id
FROM {$wpdb->term_relationships} tr
INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.term_id IN (" . implode( ',', array_unique( $exclude_term_ids ) ) . ')
) excluded_posts ON posts.ID = excluded_posts.object_id';
$terms_where_sql = ' AND excluded_posts.object_id IS NULL';
}
$sql_post_types = "('" . implode( "','", $post_types ) . "')";
$multilingual_sql = $this->multilingual_sql( $post_types );
$where_clause = ! empty( $multilingual_sql ) ? 'AND ' : 'WHERE ';
$sql = "SELECT
posts.ID,
posts.post_title,
posts.post_name,
posts.post_parent,
posts.post_type,
posts.post_date,
posts.post_date_gmt
FROM $wpdb->posts as posts
$terms_join_sql
$multilingual_sql
$where_clause post_status = 'publish' AND post_type IN $sql_post_types AND posts.post_password = ''
$exclude_old_posts_sql
$exclude_posts_sql
$terms_where_sql
GROUP BY posts.ID
ORDER BY posts.post_modified DESC";
$posts = QueryBuilder::run_query( $sql );
foreach ( $posts as $post ) {
if ( apply_filters( 'xml_sitemap_include_post', true, $post->ID ) ) {
$post_date = '0000-00-00 00:00:00' !== $post->post_date_gmt ? $post->post_date_gmt : $post->post_date;
$this->add_url(
get_permalink( $post ),
$post->ID,
apply_filters( 'xml_sitemap_google_news_title', $post->post_title, $post->ID ),
gmdate( DATE_W3C, strtotime( $post_date ) ),
$post->post_type
);
}
}
}
/**
* Add Google News Sitemap Url
*
* @param string $url
* @param int $id
* @param string $title
* @param string $last_modified
* @param string $post_type
*/
public function add_url( $url, $id, $title, $last_modified = '', $post_type = 'post' ) {
$this->urls[] = array(
$url, // URL
! empty( $this->settings->google_news_name ) ? $this->settings->google_news_name : get_bloginfo( 'name' ), // Publication Name
apply_filters( 'xml_sitemap_news_language', $this->get_blog_language(), $id, $post_type ), // Publication Language
$title, // Title
$last_modified, // Last Modified
$id, // ID
);
}
/**
* Get Blog Language
*/
public function get_blog_language() {
if ( null === $this->blog_language ) {
$this->blog_language = sgg_parse_language( get_bloginfo( 'language' ) );
}
return $this->blog_language;
}
public static function is_older_than_48h( $date ) {
$accepted_time = time() - ( 48 * 3600 );
$last_modified = strtotime( $date );
return $last_modified < $accepted_time;
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace GRIM_SG;
class ImageSitemap extends MediaSitemap {
public static $template = 'image-sitemap';
private $image_mime_types = array(
'image/jpeg',
'image/png',
'image/bmp',
'image/gif',
'image/webp',
'image/avif',
);
/**
* Adding Google News Sitemap Headers
*/
public function extraSitemapHeader() {
return array( 'xmlns:image' => 'http://www.google.com/schemas/sitemap-image/1.1' );
}
public function get_post_media( int $post_id, string $post_type ): array {
return apply_filters( 'sgg_image_sitemap_urls', array(), $post_id, $post_type );
}
public function add_urls( string $url, array $media ): void {
// Remove old URL if it exists
$this->urls = array_filter(
$this->urls,
function( $item ) use ( $url ) {
return $item[0] !== $url;
}
);
$this->urls[] = array(
$url, // URL
$media, // Images
);
}
public function filter_value( string $value ): bool {
$value = strtok( $value, '?' );
$filetype = wp_check_filetype( $value );
$filtered = in_array( $filetype['type'], $this->image_mime_types, true );
return apply_filters( 'sgg_filter_image_url', $filtered, $value );
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class ImportExport extends Controller {
public function __construct() {
add_action( 'wp_ajax_export_sitemap_settings', array( $this, 'export_settings' ) );
}
public static function import_settings() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( ! empty( $_FILES['import_file']['tmp_name'] ) ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
$import_data = file_get_contents( $_FILES['import_file']['tmp_name'] );
if ( ! empty( $import_data ) ) {
$import_data = json_decode( $import_data, true );
if ( ! empty( $import_data ) ) {
update_option( self::$slug, $import_data );
add_settings_error( self::$slug, 'import_settings', esc_html__( 'Settings imported successfully.', 'xml-sitemap-generator-for-google' ), 'success' );
return;
}
}
}
add_settings_error(
self::$slug,
'import_settings',
esc_html__( 'Invalid settings file or data.', 'xml-sitemap-generator-for-google' ),
);
}
public function export_settings() {
if ( ! current_user_can( 'manage_options' ) || ! wp_verify_nonce( $_REQUEST['nonce'], 'sgg_export_settings' ) ) {
return;
}
$settings = get_option( self::$slug );
$export_data = wp_json_encode( $settings );
header( 'Content-Description: File Transfer' );
header( 'Content-type: application/txt' );
header( 'Content-Disposition: attachment; filename="sitemap_settings.json"' );
header( 'Content-Transfer-Encoding: binary' );
header( 'Expires: 0' );
header( 'Cache-Control: must-revalidate' );
header( 'Pragma: public' );
//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $export_data;
exit;
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class IndexNow extends Controller {
private $site_url;
private $api_key;
private static $api_name = 'sgg_indexnow_api_key';
public function __construct() {
$this->set_site_url();
$this->set_api_key();
}
public function ping_site_url() {
return $this->ping_url( $this->site_url );
}
public function ping_url( $url ) {
$response = $this->request( $url );
return $this->handle_response( $response );
}
public function request( $index_url ) {
$data = wp_json_encode(
array(
'host' => $this->remove_url_scheme( $this->site_url ),
'key' => $this->api_key,
'keyLocation' => $this->get_api_key_location(),
'urlList' => array( $index_url ),
)
);
return wp_remote_post(
'https://api.indexnow.org/indexnow/',
array(
'body' => $data,
'headers' => array(
'Content-Type' => 'application/json',
),
)
);
}
private function handle_response( $response ) {
$error = array(
'status' => 'error',
'message' => __( 'IndexNow Protocol unknown error occurred', 'google-sitemap-generator' ),
);
if ( is_wp_error( $response ) ) {
return array(
'status' => 'error',
'message' => $response->get_error_message(),
);
}
if ( isset( $response['errors'] ) ) {
return $error;
}
if ( ! empty( $response['response']['code'] ) ) {
if ( in_array( $response['response']['code'], array( 200, 202 ), true ) ) {
return array(
'status' => 'success',
'message' => __( 'Changes successfully submitted to IndexNow', 'google-sitemap-generator' ),
);
} else {
if ( 400 === $response['response']['code'] ) {
$error['message'] = __( 'IndexNow Protocol Invalid Request', 'google-sitemap-generator' );
} elseif ( 403 === $response['response']['code'] ) {
$error['message'] = __( 'IndexNow Protocol Invalid Api Key', 'google-sitemap-generator' );
} elseif ( 422 === $response['response']['code'] ) {
$error['message'] = __( 'IndexNow Protocol Invalid URL', 'google-sitemap-generator' );
} elseif ( ! empty( $response['response']['message'] ) ) {
$error['message'] = sprintf(
/* translators: %s: error message */
__( 'IndexNow Protocol Error: %s', 'google-sitemap-generator' ),
$response['response']['message']
);
}
}
}
return $error;
}
public function get_api_key() {
if ( ! empty( $this->api_key ) ) {
return $this->api_key;
}
$api_key = is_multisite() ? get_site_option( self::$api_name ) : get_option( self::$api_name );
if ( $api_key ) {
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
return base64_decode( $api_key );
}
return apply_filters( 'sgg_indexnow_api_key', $api_key );
}
public function set_api_key() {
$api_key = $this->get_api_key();
if ( empty( $api_key ) ) {
$api_key = preg_replace( '[-]', '', wp_generate_uuid4() );
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
$base64_api_key = base64_encode( $api_key );
if ( is_multisite() ) {
update_site_option( self::$api_name, $base64_api_key );
} else {
update_option( self::$api_name, $base64_api_key );
}
}
$this->api_key = $api_key;
}
public static function delete_api_key() {
if ( is_multisite() ) {
delete_site_option( self::$api_name );
} else {
delete_option( self::$api_name );
}
}
public function set_site_url() {
$this->site_url = get_home_url();
}
public function get_api_key_location() {
return trailingslashit( $this->site_url ) . $this->api_key . '.txt';
}
public function remove_url_scheme( $url ) {
return preg_replace( '/^https?:\/\//', '', $url );
}
}

View File

@@ -0,0 +1,225 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\QueryBuilder;
abstract class MediaSitemap extends Sitemap {
abstract public function add_urls( string $url, array $media ): void;
abstract public function filter_value( string $value ): bool;
/**
* Add URLS Callback function
*/
public function urlsCallback() {
return 'addMediaUrl';
}
public function get_post_media( int $post_id, string $post_type ): array {
return apply_filters( 'sgg_media_post_urls', array(), $post_id, $post_type );
}
/**
* Collect Media URLs for Sitemap
*/
public function collect_urls( $template = 'sitemap', $inner_sitemap = null, $current_page = null ) {
global $wpdb;
$post_types = array( 'page', 'post' );
$template = sgg_maybe_remove_inner_suffix( $template );
$cache_enabled = ! $this->settings->disable_media_sitemap_cache;
if ( $cache_enabled ) {
$cache = new Cache( "media-$template" );
// Set URLs from cache if available.
$cached_urls = $cache->get();
if ( $cached_urls ) {
$this->urls = $cached_urls;
}
}
$sitemap_key = 'video-sitemap' === $template ? 'video_sitemap' : 'image_sitemap';
foreach ( $post_types as $key => $post_type ) {
if ( isset( $this->settings->{$post_type}->{$sitemap_key} ) && ! $this->settings->{$post_type}->{$sitemap_key} ) {
unset( $post_types[ $key ] );
}
}
if ( sgg_pro_enabled() ) {
foreach ( $this->get_cpt() as $cpt ) {
if ( ! empty( $this->settings->cpt[ $cpt ] ) && ! empty( $this->settings->cpt[ $cpt ]->{$sitemap_key} ) ) {
$post_types[] = $cpt;
}
}
}
$sql_post_types = "('" . implode( "','", $post_types ) . "')";
$multilingual_sql = $this->multilingual_sql( $post_types );
$where_clause = ! empty( $multilingual_sql ) ? 'AND ' : 'WHERE ';
$limit = 5000;
if ( $cache_enabled ) {
$last_mod_time = get_option( $this->get_option_name( $template, 'latest_mod_time' ), '1970-01-01 00:00:00' );
$last_id = get_option( $this->get_option_name( $template, 'latest_post_id' ), 0 );
}
while ( true ) {
$last_mod_sql = '';
$limit_sql = '';
if ( $cache_enabled ) {
$last_mod_sql = $wpdb->prepare(
'AND (posts.post_modified > %s OR (posts.post_modified = %s AND posts.ID > %d))',
$last_mod_time,
$last_mod_time,
$last_id
);
$limit_sql = $wpdb->prepare( 'LIMIT %d', $limit );
}
$sql = "SELECT posts.ID, posts.post_name, posts.post_parent, posts.post_content, posts.post_type, posts.post_modified
FROM {$wpdb->posts} as posts $multilingual_sql $where_clause posts.post_status = 'publish'
AND posts.post_type IN $sql_post_types AND posts.post_password = ''
$last_mod_sql ORDER BY posts.post_modified ASC, posts.ID ASC $limit_sql";
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$posts = $wpdb->get_results( $sql );
// If no posts are returned, then all posts have been processed.
if ( empty( $posts ) ) {
break;
}
// Loop through the posts and add the URLs to the sitemap.
foreach ( $posts as $post ) {
if ( ! apply_filters( 'xml_sitemap_include_post', true, $post->ID ) ) {
continue;
}
$content = apply_filters( 'xml_media_sitemap_post_content', $post->post_content, $post );
if ( ! empty( $content ) && preg_match( '/\[.+?\]/im', $content ) ) {
preg_match_all( '/\[.+?\]/im', $content, $shortcode_matches );
foreach ( $shortcode_matches as $shortcodes ) {
foreach ( $shortcodes as $shortcode ) {
// Skip HTML Sitemap Shortcode
if ( 0 !== strpos( $shortcode, '[html-sitemap' ) ) {
ob_start();
$do_shortcode = do_shortcode( $shortcode );
$output = ob_get_clean();
$final_output = $do_shortcode . $output;
$content = str_replace( $shortcode, $final_output, $content );
}
}
}
}
$media = $this->get_post_media( $post->ID, $post->post_type );
$urls = array();
if ( preg_match_all( '(https?://[-_.!~*()a-zA-Z0-9;/?:@&=+$%#纊-黑亜-熙ぁ-んァ-ヶ]+)', $content, $result ) !== false ) {
$unique_urls = array();
// Remove duplicate Image sizes URLs
foreach ( array_unique( $result[0] ) as $url ) {
$base_url = preg_replace( '/-\d+x\d+(?=\.\w{3,4}$)/', '', $url );
if ( ! isset( $unique_urls[ $base_url ] ) ) {
$unique_urls[ $base_url ] = strtok( $url, '#' );
}
}
$urls = array_values( $unique_urls );
}
$urls = apply_filters( 'sgg_sitemap_post_media_urls', $urls, $post->ID );
if ( ! empty( $urls ) ) {
foreach ( $urls as $url ) {
if ( $this->filter_value( $url ) ) {
$media[] = $url;
}
}
}
if ( ! empty( $media ) ) {
$this->add_urls( get_permalink( $post ), array_unique( $media ) );
}
$last_mod_time = $post->post_modified;
$last_id = $post->ID;
}
if ( $cache_enabled ) {
// Cache the collected URLs.
$cache->set( $this->urls );
// Save the new markers for the latest post processed.
update_option( $this->get_option_name( $template, 'latest_mod_time' ), $last_mod_time );
update_option( $this->get_option_name( $template, 'latest_post_id' ), $last_id );
}
// If fewer posts than the limit were returned, we've reached the final batch.
if ( ! $cache_enabled || count( $posts ) < $limit ) {
break;
}
}
// Set cached URLs to the sitemap URLs.
if ( $cache_enabled ) {
$this->urls = $cache->get();
if ( is_array( $this->urls ) ) {
$this->urls = array_reverse( $this->urls );
} else {
$this->urls = array();
// Delete cache if no URLs are found
self::delete_all_cache();
}
}
// Check Index Sitemap
$links_per_page = $this->settings->links_per_page ?? 1000;
$has_many_links = count( $this->urls ) > $links_per_page;
// Update Media Sitemap Structure option
update_option( "sgg_{$template}_structure", $has_many_links ? 'multiple' : 'single' );
if ( sgg_is_sitemap_index( $template, $this->settings ) && $has_many_links ) {
if ( ! empty( $inner_sitemap ) && ! empty( $current_page ) ) {
$chunks = array_chunk( $this->urls, $links_per_page );
$this->urls = $chunks[ $current_page - 1 ] ?? array();
} else {
$this->urls = array(
str_replace( '-sitemap', '', $template ) =>
array_map(
function ( $chunk ) {
return $chunk[0] ?? array();
},
array_chunk( $this->urls, $links_per_page )
),
);
}
}
}
private function get_option_name( string $template, string $name ): string {
return "sgg_{$template}_{$name}";
}
public static function delete_all_cache(): void {
delete_option( 'sgg_image-sitemap_latest_mod_time' );
delete_option( 'sgg_image-sitemap_latest_post_id' );
delete_option( 'sgg_video-sitemap_latest_mod_time' );
delete_option( 'sgg_video-sitemap_latest_post_id' );
Cache::delete( 'image-sitemap' );
Cache::delete( 'media-image-sitemap' );
Cache::delete( 'video-sitemap' );
Cache::delete( 'media-video-sitemap' );
}
}

View File

@@ -0,0 +1,63 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\SitemapGenerator;
class MultilingualSitemap extends Sitemap {
public static $template = 'multilingual-sitemap';
public function show_sitemap( $template, $is_xml = true, $inner_sitemap = null, $current_page = null ) {
remove_all_filters( 'pre_get_posts' );
$sitemap = new SitemapGenerator( sgg_get_home_url() );
$this->collect_urls( $template, $inner_sitemap, $current_page );
try {
$sitemap->createMultilingualSitemap( $this->urls );
} catch ( \Exception $exc ) {
echo $exc->getTraceAsString(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
try {
$sitemap->outputSitemap( $template, $is_xml, $inner_sitemap );
} catch ( \Exception $exc ) {
echo $exc->getTraceAsString(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
/**
* Collect Sitemap URLs
*/
public function collect_urls( $template = 'sitemap', $inner_sitemap = null, $current_page = null ) {
$this->urls[] = sgg_get_sitemap_url( $this->settings->sitemap_url, 'sitemap_xml' );
// Polylang, TranslatePress
$languages = sgg_get_languages();
$default_language = sgg_get_default_language_code();
if ( ! empty( $languages ) ) {
foreach ( $languages as $language ) {
$url = sgg_get_sitemap_url( "{$language}/{$this->settings->sitemap_url}", 'sitemap_xml' );
$this->urls[] = ! empty( $default_language )
? str_replace( "/{$default_language}/", '/', $url )
: $url;
}
}
// WPML
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
$wpml_languages = apply_filters( 'wpml_active_languages', array() );
foreach ( $wpml_languages as $language ) {
if ( apply_filters( 'wpml_default_language', null ) === $language['code'] ) {
continue;
}
$this->urls[] = esc_url( "{$language['url']}{$this->settings->sitemap_url}" );
}
}
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class Notices extends Controller {
private const RATE = 'sgg_rate';
private const BUY_PRO = 'sgg_buy_pro';
public function __construct() {
add_action( 'admin_init', array( $this, 'init_notices' ) );
add_action( 'wp_ajax_sgg_disable_notice', array( $this, 'disable_notice' ) );
}
public function disable_notice() {
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'sgg-notice' ) ) {
wp_send_json_error( array( 'message' => esc_html__( 'Invalid nonce.', 'xml-sitemap-generator-for-google' ) ) );
}
$notice = sanitize_text_field( $_POST['notice'] ?? '' );
if ( in_array( $notice, array( self::RATE, self::BUY_PRO ), true ) ) {
update_option( "sgg_disable_notice_{$notice}", true, false );
}
wp_send_json_success();
}
public function init_notices() {
$installation_time = get_option( 'sgg_installation_time' );
if ( ! $installation_time ) {
update_option( 'sgg_installation_time', time() );
} else {
$days = round( ( time() - $installation_time ) / DAY_IN_SECONDS );
$disable_rate = get_option( 'sgg_disable_notice_' . self::RATE, false );
$disable_pro = get_option( 'sgg_disable_notice_' . self::BUY_PRO, false );
add_action( 'current_screen', function ( $screen ) use ( $days, $disable_rate, $disable_pro ) {
if ( strpos( $screen->id, 'xml-sitemap-generator-for-google' ) === false ) {
return;
}
remove_all_actions( 'admin_notices' );
remove_all_actions( 'all_admin_notices' );
if ( $days >= 3 && ! $disable_rate ) {
add_action( 'admin_notices', array( $this, 'rate_notice' ) );
}
if ( $days >= 5 && ! sgg_pro_enabled() && ! $disable_pro ) {
add_action( 'admin_notices', array( $this, 'pro_notice' ) );
}
});
}
}
public function rate_notice() {
$this->enqueue_scripts();
Dashboard::render(
'partials/rate-banner.php',
array(
'label' => esc_html__( 'Hi, thank you for using Google XML Sitemaps Generator!', 'xml-sitemap-generator-for-google' ),
'description' => sprintf(
esc_html__( 'If you like the plugin, please leave us a %s rating. A huge thank you from the team in advance!', 'xml-sitemap-generator-for-google' ),
'<span><a href="' . esc_url( sgg_get_review_url() ) . '" target="_blank">★★★★★</a></span>'
),
'button_text' => esc_html__( 'Yes, Rate Now', 'xml-sitemap-generator-for-google' ),
'button_url' => esc_url( sgg_get_review_url() ),
'data_notice' => self::RATE,
'notice_class' => 'grim-dynamic-notice',
)
);
}
public function pro_notice() {
$this->enqueue_scripts();
Dashboard::render(
'partials/rate-banner.php',
array(
'label' => esc_html__( 'Hi, thank you for using Google XML Sitemaps Generator!', 'xml-sitemap-generator-for-google' ),
'description' => sprintf(
esc_html__( 'If you want to unlock more features, please check out our %s.', 'xml-sitemap-generator-for-google' ),
'<a href="' . esc_url( sgg_get_pro_url( 'notice' ) ) . '" target="_blank">' . esc_html__( 'Pro version', 'xml-sitemap-generator-for-google' ) . '</a>'
),
'button_text' => esc_html__( 'Yes, Read More', 'xml-sitemap-generator-for-google' ),
'button_url' => esc_url( sgg_get_pro_url( 'notice' ) ),
'data_notice' => self::BUY_PRO,
'notice_class' => 'grim-pro-notice grim-dynamic-notice',
)
);
}
public function enqueue_scripts() {
wp_enqueue_script( 'sgg-notices', GRIM_SG_URL . 'assets/js/notices.js', array( 'jquery' ), GRIM_SG_VERSION, true );
wp_localize_script(
'sgg-notices',
'sggNotice',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'sgg-notice' ),
)
);
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace GRIM_SG;
class PostSettings {
public function __construct() {
add_action( 'init', array( $this, 'register_post_meta' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'register_plugin_sidebar_block' ) );
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
add_action( 'save_post', array( $this, 'save_meta_box' ) );
add_action( 'edit_attachment', array( $this, 'save_meta_box' ) );
add_filter( 'user_has_cap', array( $this, 'allow_edit_post_meta' ), 10, 3 );
}
/**
* Registers protected Post Meta fields.
*/
public function register_post_meta() {
register_post_meta(
'',
'_sitemap_exclude',
array(
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
)
);
register_post_meta(
'',
'_sitemap_priority',
array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
)
);
register_post_meta(
'',
'_sitemap_frequency',
array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
)
);
}
/**
* Registers Gutenberg Plugin Sidebar Block.
*/
public function register_plugin_sidebar_block() {
$assets_file = GRIM_SG_PATH . '/assets/gutenberg/build/plugin-sidebar.asset.php';
if ( file_exists( $assets_file ) ) {
$assets = include $assets_file;
wp_enqueue_script(
'sitemap-settings',
GRIM_SG_URL . 'assets/gutenberg/build/plugin-sidebar.js',
$assets['dependencies'],
$assets['version'],
true
);
wp_localize_script(
'sitemap-settings',
'sitemapSettings',
array(
'isProEnabled' => sgg_pro_enabled(),
'isExcludeEnabled' => intval( ! apply_filters( 'xml_sitemap_disable_post_meta__exclude_sitemap', false ) ),
'isPriorityEnabled' => intval( ! apply_filters( 'xml_sitemap_disable_post_meta__sitemap_priority', false ) ),
'isFrequencyEnabled' => intval( ! apply_filters( 'xml_sitemap_disable_post_meta__sitemap_frequency', false ) ),
)
);
}
}
/**
* Registers Post Metabox.
*/
public function add_meta_box() {
// Disable Meta Box fields.
if ( apply_filters( 'xml_sitemap_disable_post_meta_fields', false ) ) {
return;
}
$public_post_types = get_post_types(
array(
'public' => true,
)
);
foreach ( $public_post_types as $post_type ) {
add_meta_box(
'sgg_pro_meta_box',
esc_html__( 'XML Sitemap Options', 'xml-sitemap-generator-for-google' ),
array( $this, 'meta_box_render' ),
$post_type,
);
}
}
/**
* Renders Post Metabox.
*/
public function meta_box_render( $post ) {
load_template(
GRIM_SG_PATH . '/templates/post-meta-box.php',
false,
compact( 'post' )
);
}
/**
* Saves Post Metabox.
*/
public function save_meta_box( $post_id ) {
if ( ! isset( $_POST['sgg_pro_meta_box_nonce'] ) || ! wp_verify_nonce( $_POST['sgg_pro_meta_box_nonce'], 'sgg_pro_meta_box' ) ) {
return;
}
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_posts' ) || ! sgg_pro_enabled() ) {
return;
}
update_post_meta( $post_id, '_sitemap_exclude', $_POST['_sitemap_exclude'] ?? '' );
if ( isset( $_POST['_sitemap_priority'] ) ) {
update_post_meta( $post_id, '_sitemap_priority', sanitize_text_field( $_POST['_sitemap_priority'] ) );
}
if ( isset( $_POST['_sitemap_frequency'] ) ) {
update_post_meta( $post_id, '_sitemap_frequency', sanitize_text_field( $_POST['_sitemap_frequency'] ) );
}
}
/**
* Allow editing protected Post Meta fields.
*/
public function allow_edit_post_meta( $allcaps, $caps, $args ) {
if ( ! empty( $args[0] ) && ! empty( $args[3] ) && 'edit_post_meta' === $args[0]
&& in_array( $args[3], array( '_sitemap_exclude', '_sitemap_priority', '_sitemap_frequency' ), true ) ) {
$allcaps['edit_post_meta'] = current_user_can( 'edit_posts' );
}
return $allcaps;
}
}

View File

@@ -0,0 +1,906 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
use GRIM_SG\Vendor\QueryBuilder;
use GRIM_SG\Vendor\SitemapGenerator;
class Sitemap extends Controller {
public static $template = 'sitemap';
public $urls = array();
public $settings;
public function __construct() {
$this->settings = $this->get_settings();
}
/**
* Generate Sitemap
*/
public function show_sitemap( $template, $is_xml = true, $inner_sitemap = null, $current_page = null ) {
if ( sgg_is_sitemap_index( $template, $this->settings ) && ! empty( $inner_sitemap ) ) {
if ( in_array( $template, array( ImageSitemap::$template, VideoSitemap::$template ), true ) ) {
$template .= '-inner-sitemap';
} else {
$template = 'inner-sitemap';
}
}
$sitemap = $this->generate_sitemap( $template, $is_xml, $inner_sitemap, $current_page );
try {
$sitemap->outputSitemap( $template, $is_xml, $inner_sitemap );
} catch ( \Exception $exc ) {
echo $exc->getTraceAsString(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
/**
* Generate Sitemap
*/
public function generate_sitemap( $template = 'sitemap', $is_xml = true, $inner_sitemap = null, $current_page = null ) {
remove_all_filters( 'pre_get_posts' );
$sitemap = new SitemapGenerator( sgg_get_home_url() );
if ( $this->settings->enable_cache ) {
$cache = new Cache( $template, $inner_sitemap, $current_page );
$urls = $cache->get();
if ( $urls ) {
$this->urls = $urls;
} else {
$this->collect_urls( $template, $inner_sitemap, $current_page );
$cache->set( $this->urls );
}
} else {
$this->collect_urls( $template, $inner_sitemap, $current_page );
}
$sitemap->addUrls( apply_filters( 'sgg_sitemap_urls', $this->urls ), $this->urlsCallback(), $template );
try {
$sitemap->createSitemap( $template, $this->extraSitemapHeader(), $is_xml );
} catch ( \Exception $exc ) {
echo $exc->getTraceAsString(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
return $sitemap;
}
/**
* Generate Sitemap XSL Template
*/
public static function generate_sitemap_xsl( $template = 'sitemap' ) {
ob_get_clean();
header( 'Content-Type: text/xsl; charset=utf-8' );
header( 'X-Robots-Tag: noindex' );
ob_start();
global $wp_version;
if ( version_compare( $wp_version, '5.5.0', '<' ) ) {
set_query_var( 'args', array( 'template' => $template ) );
}
load_template(
GRIM_SG_PATH . '/templates/xsl/sitemap.php',
false,
compact( 'template' )
);
ob_end_flush();
}
/**
* Get Sitemap Table by Template
*/
public static function get_sitemap_table( $template = 'sitemap', $args = array() ) {
switch ( $template ) {
case GoogleNews::$template:
$table = 'google-news';
break;
case ImageSitemap::$template:
$table = 'image-sitemap';
break;
case VideoSitemap::$template:
$table = 'video-sitemap';
break;
case 'sitemap-index':
case MultilingualSitemap::$template:
$table = 'sitemap-index';
break;
default:
$table = 'sitemap';
break;
}
load_template( GRIM_SG_PATH . "/templates/xsl/tables/{$table}.php", false, $args );
}
/**
* Get Sitemap Title by Template
*/
public static function get_sitemap_title( $template ) {
$title = __( 'Sitemap', 'xml-sitemap-generator-for-google' );
switch ( $template ) {
case \GRIM_SG\GoogleNews::$template:
$title = __( 'Google News', 'xml-sitemap-generator-for-google' );
break;
case \GRIM_SG\ImageSitemap::$template:
$title = __( 'Image Sitemap', 'xml-sitemap-generator-for-google' );
break;
case \GRIM_SG\VideoSitemap::$template:
$title = __( 'Video Sitemap', 'xml-sitemap-generator-for-google' );
break;
case \GRIM_SG\MultilingualSitemap::$template:
$title = __( 'Multilingual Sitemap', 'xml-sitemap-generator-for-google' );
break;
case 'inner-sitemap':
$title = __( 'Sitemap', 'xml-sitemap-generator-for-google' );
break;
case 'sitemap-index':
$title = __( 'Sitemap Index', 'xml-sitemap-generator-for-google' );
break;
}
return $title;
}
/**
* Add URLS Callback function
*/
public function urlsCallback() {
return 'addUrl';
}
/**
* Adding Google News Sitemap Headers
*/
public function extraSitemapHeader() {
return array();
}
/**
* Collect Sitemap URLs
*/
public function collect_urls( $template = 'sitemap', $inner_sitemap = null, $current_page = null ) {
if ( $this->settings->home->include && ! $this->settings->page->include ) {
$this->add_home();
}
if ( sgg_is_sitemap_index( $template, $this->settings ) ) {
$current_page = ! empty( $current_page ) ? intval( $current_page ) - 1 : $current_page;
if ( 'sitemap' === $template ) {
$post_types = $this->get_post_types_list( array( 'page', 'post' ), $this->settings );
foreach ( $post_types as $post_type ) {
$this->add_posts( $post_type, $current_page, true );
}
$this->add_categories( $current_page, true );
$this->add_authors( $current_page, true );
$this->add_archives( true );
$this->add_media( $current_page, true );
$this->add_additional_pages( true );
} else {
switch ( $inner_sitemap ) {
case 'category':
$this->add_categories( $current_page );
break;
case 'author':
$this->add_authors( $current_page );
break;
case 'archive':
$this->add_archives();
break;
case 'media':
$this->add_media( $current_page );
break;
case 'additional':
$this->add_additional_pages();
break;
default:
$this->add_posts( $inner_sitemap, $current_page );
break;
}
}
} else {
$this->add_posts();
$this->add_not_translatable_posts(); // Add Not Translatable Post Types to All Sitemaps
$this->add_categories();
$this->add_authors();
$this->add_archives();
$this->add_media();
$this->add_additional_pages();
}
}
/**
* Add Home Page to Sitemap
*/
public function add_home() {
$home = $this->settings->home;
if ( $home->include ) {
$front_page_id = get_option( 'page_on_front' );
$last_modified = ( $front_page_id ) ? get_post_modified_time( DATE_W3C, false, $front_page_id ) : gmdate( 'c' );
$this->add_url(
sgg_get_home_url_with_trailing_slash(),
$home->priority,
$home->frequency,
$last_modified,
'page'
);
}
}
/**
* Add all Posts to Sitemap
*/
public function add_posts( $post_type = null, $current_page = null, $is_sitemap_index = false ) {
global $wpdb;
$front_page_id = get_option( 'page_on_front' );
$exclude_post_ids = apply_filters( 'sgg_sitemap_exclude_post_ids', apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->exclude_posts ?? '' ) );
$exclude_term_ids = apply_filters( 'sgg_sitemap_exclude_term_ids', apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->exclude_terms ?? '' ) );
$include_term_ids = apply_filters( 'sgg_sitemap_include_only_term_ids', apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->include_only_terms ?? '' ) );
$per_page = intval( $this->settings->links_per_page ?? 1000 );
if ( ! empty( $front_page_id ) ) {
$exclude_post_ids[] = $front_page_id;
}
$exclude_posts_sql = '';
if ( ! empty( $exclude_post_ids ) ) {
$exclude_posts_sql = 'AND posts.ID NOT IN (' . implode( ',', array_unique( $exclude_post_ids ) ) . ')';
}
$terms_join_sql = '';
$terms_where_sql = '';
if ( ! empty( $include_term_ids ) ) {
$terms_join_sql = "INNER JOIN (
SELECT DISTINCT tr.object_id
FROM {$wpdb->term_relationships} tr
INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.term_id IN (" . implode( ',', array_unique( $include_term_ids ) ) . ')
) included_posts ON posts.ID = included_posts.object_id';
} elseif ( ! empty( $exclude_term_ids ) ) {
$terms_join_sql = "LEFT JOIN (
SELECT DISTINCT tr.object_id
FROM {$wpdb->term_relationships} tr
INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.term_id IN (" . implode( ',', array_unique( $exclude_term_ids ) ) . ')
) excluded_posts ON posts.ID = excluded_posts.object_id';
$terms_where_sql = ' AND excluded_posts.object_id IS NULL';
}
if ( ! empty( $post_type ) ) {
if ( ( isset( $this->settings->{$post_type}->include ) && $this->settings->{$post_type}->include )
|| ( ! empty( $this->settings->cpt[ $post_type ] ) && ! empty( $this->settings->cpt[ $post_type ]->include ) ) ) {
$post_types = array( $post_type );
}
} else {
$post_types = $this->get_post_types_list( array( 'page', 'post' ), $this->settings );
}
if ( empty( $post_types ) ) {
return;
}
if ( in_array( 'page', $post_types, true ) && 1 > $current_page ) {
$this->add_home();
}
$sql_extra_select = '';
$sql_post_types = "('" . implode( "','", $post_types ) . "')";
$multilingual_sql = $this->multilingual_sql( $post_types );
$where_clause = ! empty( $multilingual_sql ) ? 'AND ' : 'WHERE ';
if ( sgg_pro_enabled() && ! empty( $this->settings->posts_priority ) ) {
$sql_extra_select .= ', posts.comment_count';
}
$sql = "SELECT
posts.ID,
posts.post_name,
posts.post_parent,
posts.post_type,
posts.post_date,
posts.post_modified
$sql_extra_select
FROM $wpdb->posts as posts
$terms_join_sql
$multilingual_sql
$where_clause posts.post_status = 'publish' AND posts.post_type IN $sql_post_types AND posts.post_password = ''
$exclude_posts_sql
$terms_where_sql
GROUP BY posts.ID
ORDER BY posts.post_modified DESC";
if ( is_null( $current_page ) && ! $is_sitemap_index ) {
$this->add_post_urls( $sql, false );
return;
}
if ( $is_sitemap_index ) {
// Calculate total number of posts
$total_posts_sql = "SELECT COUNT(*) FROM $wpdb->posts as posts
$terms_join_sql
$multilingual_sql
$where_clause posts.post_status = 'publish' AND posts.post_type IN $sql_post_types AND posts.post_password = ''
$exclude_posts_sql
$terms_where_sql
ORDER BY posts.post_modified DESC";
$total_posts = $wpdb->get_var( $total_posts_sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
// Calculate the number of chunks
$num_chunks = ceil( $total_posts / $per_page );
for ( $chunk_index = 0; $chunk_index < $num_chunks; $chunk_index++ ) {
$offset = $chunk_index * $per_page;
$chunk_sql = $sql . " LIMIT $offset, 1";
$this->add_post_urls( $chunk_sql, true );
}
} else {
$offset = $current_page * $per_page;
$sql .= " LIMIT $offset, $per_page";
$this->add_post_urls( $sql, false );
}
}
/**
* Add Post URLs to Sitemap
*/
public function add_post_urls( $sql, $is_sitemap_index ) {
$priority_provider = $this->get_posts_priority_provider();
$posts = QueryBuilder::run_query( $sql );
foreach ( $posts as $post ) {
if ( $is_sitemap_index || apply_filters( 'xml_sitemap_include_post', true, $post->ID ) ) {
$this->add_url(
get_permalink( $post ),
( null !== $priority_provider && 'post' === $post->post_type )
? apply_filters( 'sitemap_post_priority', $priority_provider->get_post_priority( $post->comment_count ), $post->ID )
: apply_filters( 'sitemap_post_priority', $this->get_post_settings( $post->post_type, 'priority' ), $post->ID ),
apply_filters( 'sitemap_post_frequency', $this->get_post_settings( $post->post_type, 'frequency' ), $post->ID ),
gmdate( DATE_W3C, strtotime( $post->post_modified ) ),
$post->post_type
);
}
}
}
/**
* Add all Categories & Tags
*/
public function add_categories( $current_page = null, $is_sitemap_index = false ) {
global $wpdb;
$taxonomy_types = array();
$per_page = intval( $this->settings->links_per_page ?? 1000 );
foreach ( $this->get_taxonomy_types( 'names' ) as $taxonomy_type ) {
if ( ! empty( $this->settings->taxonomies[ $taxonomy_type ] ) && $this->settings->taxonomies[ $taxonomy_type ]->include ) {
$taxonomy_types[] = $taxonomy_type;
}
}
if ( empty( $taxonomy_types ) ) {
return;
}
$exclude_term_ids = apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->exclude_terms ?? '' );
$include_term_ids = apply_filters( 'sgg_sitemap_exclude_ids', array(), $this->settings->include_only_terms ?? '' );
$terms_where_sql = '';
if ( ! empty( $include_term_ids ) ) {
$terms_where_sql = 'AND terms.term_id IN (' . implode( ',', array_unique( $include_term_ids ) ) . ')';
} elseif ( ! empty( $exclude_term_ids ) ) {
$terms_where_sql = 'AND terms.term_id NOT IN (' . implode( ',', array_unique( $exclude_term_ids ) ) . ')';
}
$post_types = $this->get_post_types_list( array( 'post' ), $this->settings );
$sql_post_types = "('" . implode( "','", $post_types ) . "')";
$sql_taxonomies = "('" . implode( "','", $taxonomy_types ) . "')";
$multilingual_sql = $this->multilingual_sql( $taxonomy_types, true );
$where_clause = ! empty( $multilingual_sql ) ? 'AND ' : 'WHERE ';
$terms_query = "
SELECT terms.*, term_taxonomy.taxonomy, term_taxonomy.count, (
SELECT MAX(p.post_modified)
FROM $wpdb->posts AS p
INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id
WHERE p.post_type IN $sql_post_types
AND p.post_status = 'publish'
AND tr.term_taxonomy_id = term_taxonomy.term_taxonomy_id
) AS post_modified
FROM $wpdb->terms AS terms
INNER JOIN $wpdb->term_taxonomy AS term_taxonomy ON terms.term_id = term_taxonomy.term_id
$multilingual_sql
$where_clause term_taxonomy.taxonomy IN $sql_taxonomies
$terms_where_sql
AND term_taxonomy.count > 0
GROUP BY terms.term_id
ORDER BY post_modified DESC, terms.name ASC
";
if ( is_null( $current_page ) && ! $is_sitemap_index ) {
$this->add_category_urls( $terms_query, false );
return;
}
if ( $is_sitemap_index ) {
// Calculate total number of terms
$total_terms_sql = "
SELECT COUNT(*) FROM $wpdb->terms AS terms
INNER JOIN $wpdb->term_taxonomy AS term_taxonomy ON terms.term_id = term_taxonomy.term_id
$multilingual_sql
$where_clause term_taxonomy.taxonomy IN $sql_taxonomies
$terms_where_sql
AND term_taxonomy.count > 0
";
$total_terms = $wpdb->get_var( $total_terms_sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
// Calculate the number of chunks
$num_chunks = ceil( $total_terms / $per_page );
for ( $chunk_index = 0; $chunk_index < $num_chunks; $chunk_index++ ) {
$offset = $chunk_index * $per_page;
$chunk_sql = $terms_query . " LIMIT $offset, 1";
$this->add_category_urls( $chunk_sql, true );
}
} else {
$offset = $current_page * $per_page;
$terms_query .= " LIMIT $offset, $per_page";
$this->add_category_urls( $terms_query, false );
}
}
/**
* Add Category URLs to Sitemap
*/
public function add_category_urls( $terms_query, $is_sitemap_index ) {
global $wpdb;
$terms = $wpdb->get_results( $terms_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
foreach ( $terms as $term ) {
if ( ! $is_sitemap_index && apply_filters( 'sgg_sitemap_exclude_single_term', false, intval( $term->term_id ), $term->taxonomy ) ) {
continue;
}
$term_modified = ! empty( $term->post_modified )
? strtotime( $term->post_modified )
: time();
$this->add_url(
get_term_link( $term ),
apply_filters( 'sitemap_term_priority', $this->get_taxonomy_settings( $term->taxonomy, 'priority' ), $term->term_id ),
apply_filters( 'sitemap_term_frequency', $this->get_taxonomy_settings( $term->taxonomy, 'frequency' ), $term->term_id ),
gmdate( DATE_W3C, $term_modified ),
'category'
);
}
}
/**
* Add all Authors of Posts
*/
public function add_authors( $current_page = null, $is_sitemap_index = false ) {
if ( ! $this->settings->authors->include ) {
return;
}
$args = array(
'has_published_posts' => $this->get_post_types_list( array( 'post' ), $this->settings ),
'fields' => 'ids',
'orderby' => 'post_count',
'order' => 'DESC',
'number' => -1,
);
if ( is_null( $current_page ) && ! $is_sitemap_index ) {
$this->add_author_urls( $args );
return;
}
$per_page = intval( $this->settings->links_per_page ?? 1000 );
if ( $is_sitemap_index ) {
$authors_query = new \WP_User_Query( $args );
if ( empty( $authors_query->get_total() ) ) {
return;
}
$num_chunks = ceil( $authors_query->get_total() / $per_page );
for ( $chunk_index = 0; $chunk_index < $num_chunks; $chunk_index++ ) {
$offset = $chunk_index * $per_page;
$args = array_merge(
$args,
array(
'number' => 1,
'offset' => $offset,
)
);
$this->add_author_urls( $args );
}
} else {
$offset = $current_page * $per_page;
$args = array_merge(
$args,
array(
'number' => $per_page,
'offset' => $offset,
)
);
$this->add_author_urls( $args );
}
}
public function add_author_urls( $args ) {
$authors_query = new \WP_User_Query( $args );
$authors = $authors_query->get_results();
if ( ! empty( $authors ) ) {
global $wpdb;
foreach ( $authors as $author_id ) {
$latest_post_query = "SELECT ID, post_modified
FROM {$wpdb->posts}
WHERE post_author = {$author_id}
AND post_type = 'post' AND post_status = 'publish'
ORDER BY post_modified DESC
LIMIT 1";
$latest_post = $wpdb->get_row( $latest_post_query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$modified_time = ! empty( $latest_post->post_modified )
? gmdate( DATE_W3C, strtotime( $latest_post->post_modified ) )
: gmdate( DATE_W3C );
$this->add_url(
get_author_posts_url( $author_id ),
$this->settings->authors->priority,
$this->settings->authors->frequency,
$modified_time,
'author'
);
}
}
}
/**
* Add all Archives
*/
public function add_archives( $is_sitemap_index = false ) {
global $wpdb;
$sql_multilingual = $this->multilingual_sql( array( 'post' ) );
$where_clause = ! empty( $sql_multilingual ) ? 'AND ' : 'WHERE ';
$sql = "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, post_date AS post_date, count(ID) as count_posts
FROM $wpdb->posts as posts
$sql_multilingual
$where_clause post_type = 'post' AND post_status = 'publish' AND post_password = ''
GROUP BY YEAR(post_date), MONTH(post_date)
ORDER BY post_date DESC";
if ( $is_sitemap_index ) {
$sql .= ' LIMIT 1';
}
$archives = QueryBuilder::run_query( $sql );
foreach ( $archives as $archive ) {
$option = ( gmdate( 'n' ) === $archive->month && gmdate( 'Y' ) === $archive->year ) ? 'archive' : 'archive_older';
if ( $this->settings->{$option}->include ) {
$this->add_url(
get_month_link( $archive->year, $archive->month ),
$this->settings->{$option}->priority,
$this->settings->{$option}->frequency,
gmdate( DATE_W3C, strtotime( $archive->post_date ) ),
'archive'
);
}
}
}
/**
* Add Media Pages (Attachments)
*/
public function add_media( $current_page = null, $is_sitemap_index = false ) {
if ( ! $this->settings->media->include ) {
return;
}
if ( ! get_option( 'wp_attachment_pages_enabled' ) ) {
return;
}
global $wpdb;
$per_page = intval( $this->settings->links_per_page ?? 1000 );
$multilingual_sql = $this->multilingual_sql( array( 'attachment' ) );
$where_clause = ! empty( $multilingual_sql ) ? 'AND ' : 'WHERE ';
$sql = "SELECT
posts.ID,
posts.post_name,
posts.post_parent,
posts.post_type,
posts.post_date,
posts.post_modified
FROM $wpdb->posts as posts
$multilingual_sql
$where_clause posts.post_status = 'inherit' AND posts.post_type = 'attachment' AND posts.post_password = ''
GROUP BY posts.ID
ORDER BY posts.post_modified DESC";
if ( is_null( $current_page ) && ! $is_sitemap_index ) {
$this->add_media_urls( $sql, false );
return;
}
if ( $is_sitemap_index ) {
// Calculate total number of attachments
$total_media_sql = "SELECT COUNT(*) FROM $wpdb->posts as posts
$multilingual_sql
$where_clause posts.post_status = 'inherit' AND posts.post_type = 'attachment' AND posts.post_password = ''
ORDER BY posts.post_modified DESC";
$total_media = $wpdb->get_var( $total_media_sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
// Calculate the number of chunks
$num_chunks = ceil( $total_media / $per_page );
for ( $chunk_index = 0; $chunk_index < $num_chunks; $chunk_index++ ) {
$offset = $chunk_index * $per_page;
$chunk_sql = $sql . " LIMIT $offset, 1";
$this->add_media_urls( $chunk_sql, true );
}
} else {
$offset = $current_page * $per_page;
$sql .= " LIMIT $offset, $per_page";
$this->add_media_urls( $sql, false );
}
}
/**
* Add Media URLs to Sitemap
*/
public function add_media_urls( $sql, $is_sitemap_index ) {
$attachments = QueryBuilder::run_query( $sql );
foreach ( $attachments as $attachment ) {
if ( $is_sitemap_index || apply_filters( 'xml_sitemap_include_post', true, $attachment->ID ) ) {
$attachment_link = get_attachment_link( $attachment->ID );
// Only add if attachment link is valid (attachment pages are enabled)
if ( $attachment_link ) {
$this->add_url(
$attachment_link,
apply_filters( 'sitemap_media_priority', apply_filters( 'sitemap_post_priority', $this->settings->media->priority, $attachment->ID ), $attachment->ID ),
apply_filters( 'sitemap_media_frequency', apply_filters( 'sitemap_post_frequency', $this->settings->media->frequency, $attachment->ID ), $attachment->ID ),
gmdate( DATE_W3C, strtotime( $attachment->post_modified ) ),
'media'
);
}
}
}
}
/**
* Add Additional Pages
*/
public function add_additional_pages( $is_sitemap_index = false ) {
$pages = $this->settings->additional_pages;
if ( empty( $pages ) ) {
return;
}
if ( $is_sitemap_index ) {
usort(
$pages,
function ( $a, $b ) {
return strtotime( $b['lastmod'] ) - strtotime( $a['lastmod'] );
}
);
$pages = array( $pages[0] );
}
foreach ( $pages as $page ) {
if ( empty( $page['url'] ) ) {
continue;
}
$last_modified = ! empty( $page['lastmod'] )
? gmdate( DATE_W3C, strtotime( $page['lastmod'] ) )
: gmdate( DATE_W3C );
$this->add_url(
$page['url'],
$page['priority'],
$page['frequency'],
$last_modified,
'additional'
);
}
}
/**
* Add Sitemap Url
*
* @param $url
* @param $priority
* @param $frequency
* @param string $last_modified
*/
public function add_url( $url, $priority, $frequency, $last_modified = '', $inner_sitemap = '' ) {
$item = array(
$url, // URL
$last_modified, // Last Modified
$frequency, // Frequency
number_format( floatval( $priority / 10 ), 1, '.', '' ), // Priority
);
if ( sgg_is_sitemap_index( 'sitemap', $this->settings ) ) {
$this->urls[ $inner_sitemap ][] = $item;
} else {
$this->urls[] = $item;
}
}
public function multilingual_sql( $element_types, $is_taxonomy = false ) {
global $wpdb;
$multilingual_sql = '';
$element_id_column = $is_taxonomy ? 'term_taxonomy.term_taxonomy_id' : 'posts.ID';
if ( function_exists( 'pll_languages_list' ) && ! empty( $GLOBALS['polylang'] ) ) {
global $polylang;
$current_language = pll_current_language();
$polylang_model = $polylang->model;
$lang_model = $polylang_model->get_language( $current_language );
$tax_language = $is_taxonomy ? $polylang_model->term->get_tax_language() : $polylang_model->post->get_tax_language();
$polylang_term_ids = array();
foreach ( $element_types as $key => $element_type ) {
$translatable = $is_taxonomy
? $polylang_model->is_translated_taxonomy( $element_type )
: $polylang_model->is_translated_post_type( $element_type );
if ( ! $translatable ) {
continue;
}
if ( $lang_model ) {
$polylang_term_ids[] = absint( $lang_model->get_tax_prop( $tax_language, 'term_taxonomy_id' ) );
}
}
if ( ! empty( $polylang_term_ids ) ) {
$polylang_term_ids = '(' . implode( ',', array_unique( $polylang_term_ids ) ) . ')';
$multilingual_sql = "INNER JOIN {$wpdb->term_relationships} AS pll_tr ON $element_id_column = pll_tr.object_id WHERE ( pll_tr.term_taxonomy_id IN $polylang_term_ids )";
}
}
if ( defined( 'ICL_SITEPRESS_VERSION' ) && ! empty( $element_types ) ) {
$current_language = apply_filters( 'wpml_current_language', null );
$element_type = $is_taxonomy ? 'tax' : 'post';
$wpml_element_types = array_map(
function ( $post_type ) use ( $element_type ) {
return "{$element_type}_{$post_type}";
},
$element_types
);
$sql_element_types = "('" . implode( "','", $wpml_element_types ) . "')";
$multilingual_sql = "INNER JOIN {$wpdb->prefix}icl_translations AS translations ON $element_id_column = translations.element_id
WHERE translations.language_code = '$current_language' AND translations.element_type IN $sql_element_types";
}
return $multilingual_sql;
}
public function add_not_translatable_posts() {
// Add Polylang Not Translatable Post Types
if ( function_exists( 'pll_languages_list' ) && ! empty( $GLOBALS['polylang'] ) ) {
$options = get_option( 'polylang' );
$post_types = $this->get_post_types_list( array(), $this->settings );
$not_translatable = ! empty( $options['post_types'] ) && ! empty( $post_types )
? array_diff( $post_types, $options['post_types'] )
: array();
if ( ! empty( $not_translatable ) ) {
foreach ( $not_translatable as $post_type ) {
$this->add_posts( $post_type );
}
}
}
}
/**
* Posts Priority
*/
public function get_posts_priority_provider() {
$class_name = str_replace( '/', '\\', $this->settings->posts_priority ?? '' );
return class_exists( $class_name ) ? new $class_name( $this->get_comments_count(), $this->get_posts_count() ) : null;
}
public function get_comments_count() {
global $wpdb;
$cache_key = self::$slug . '_comments_count';
$comments_count = wp_cache_get( $cache_key, self::$slug );
if ( false === $comments_count ) {
$comments_count = $wpdb->get_var( "SELECT COUNT(*) as `comments_count` FROM {$wpdb->comments} WHERE `comment_approved`='1'" );
wp_cache_set( $cache_key, $comments_count, self::$slug, 20 );
}
return $comments_count;
}
public function get_posts_count() {
global $wpdb;
$cache_key = self::$slug . '_posts_count';
$posts_count = wp_cache_get( $cache_key, self::$slug );
if ( false === $posts_count ) {
$posts_count = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} p WHERE p.post_password = '' AND p.post_type = 'post' AND p.post_status = 'publish' " );
wp_cache_set( $cache_key, $posts_count, self::$slug, 20 );
}
return $posts_count;
}
/**
* Get Post Field Value
*
* @param $post_type
* @param $field
* @return mixed
*/
public function get_post_settings( $post_type, $field ) {
if ( ! empty( $this->settings->cpt ) && in_array( $post_type, array_keys( $this->settings->cpt ), true ) ) {
return $this->settings->cpt[ $post_type ]->{$field} ?? null;
}
return $this->settings->{$post_type}->{$field} ?? null;
}
/**
* Get Taxonomy Field Value
*
* @param $taxonomy_type
* @param $field
* @return mixed
*/
public function get_taxonomy_settings( $taxonomy_type, $field ) {
if ( ! empty( $this->settings->taxonomies ) && in_array( $taxonomy_type, array_keys( $this->settings->taxonomies ), true ) ) {
return $this->settings->taxonomies[ $taxonomy_type ]->{$field} ?? null;
}
return $this->settings->{$taxonomy_type}->{$field} ?? null;
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace GRIM_SG;
if ( ! defined( 'WP_CLI' ) || ! WP_CLI ) {
return;
}
use \WP_CLI;
class SitemapCLI {
/**
* Generate a sitemap.
*
* ## OPTIONS
*
* [--template=<template>]
* : The sitemap template to use. Default: 'sitemap'
*
* ## EXAMPLES
*
* # Generate a sitemap
* $ wp sitemap generate
*
* # Generate a specific Sitemap type
* $ wp sitemap generate --template=sitemap
* $ wp sitemap generate --template=image-sitemap
* $ wp sitemap generate --template=video-sitemap
* $ wp sitemap generate --template=google-news
*
* @param array $args Command arguments
* @param array $assoc_args Command associative arguments
*/
public function generate( $args, $assoc_args ) {
$template = $assoc_args['template'] ?? 'sitemap';
$inner_sitemap = null;
$current_page = null;
$allowed_templates = array(
'sitemap',
'image-sitemap',
'video-sitemap',
'google-news',
);
if ( ! in_array( $template, $allowed_templates, true ) ) {
WP_CLI::error( 'Invalid Sitemap Template. Allowed templates: ' . implode( ', ', $allowed_templates ) );
}
// Initialize the Sitemap class
$sitemap = null;
if ( 'sitemap' === $template ) {
$sitemap = new Sitemap();
} elseif ( 'image-sitemap' === $template ) {
$sitemap = new ImageSitemap();
} elseif ( 'video-sitemap' === $template ) {
$sitemap = new VideoSitemap();
} elseif ( 'google-news' === $template ) {
$sitemap = new GoogleNews();
}
if ( ! $sitemap ) {
WP_CLI::error( 'Sitemap class not found.' );
}
if ( $sitemap->settings->enable_cache ) {
$cache = new Cache( $template, $inner_sitemap, $current_page );
$sitemap->collect_urls( $template, $inner_sitemap, $current_page );
$cache->set( $sitemap->urls );
} else {
$sitemap->collect_urls( $template, $inner_sitemap, $current_page );
}
WP_CLI::success(
"Sitemap generated successfully for template: {$template}. URLs count: " . count( $sitemap->urls )
);
}
}
// Register the command
WP_CLI::add_command( 'sitemap', 'GRIM_SG\SitemapCLI' );

View File

@@ -0,0 +1,53 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class Tools extends Controller {
public function __construct() {
add_action( 'transition_post_status', array( $this, 'transition_post_status' ), 100, 3 );
}
public function transition_post_status( $new_status, $old_status, $post ) {
$settings = $this->get_settings();
// Ping IndexNow
if ( $settings->enable_indexnow && 'publish' === $new_status ) {
( new IndexNow() )->ping_url( get_permalink( $post ) );
}
}
public static function run_tools_actions( $data = array() ) {
if ( ! empty( $data['sgg-indexnow'] ) ) {
$response = ( new IndexNow() )->ping_site_url();
add_settings_error(
Controller::$slug,
'indexnow_notice',
$response['message'],
$response['status']
);
return true;
} elseif ( ! empty( $data['sgg-flush-rewrite-rules'] ) ) {
Frontend::activate_plugin();
self::add_admin_notice( __( 'WordPress Rewrite Rules flushed.', 'xml-sitemap-generator-for-google' ) );
return true;
} elseif ( ! empty( $data['sgg-clear-cache'] ) ) {
Cache::clear();
self::add_admin_notice( __( 'Sitemaps Cache cleared.', 'xml-sitemap-generator-for-google' ) );
return true;
}
return false;
}
public static function add_admin_notice( $message ) {
add_settings_error( Controller::$slug, 'sitemap_tools', $message, 'success' );
}
}

View File

@@ -0,0 +1,133 @@
<?php
namespace GRIM_SG;
use SGG_PRO\Classes\Video_Sitemap;
class VideoSitemap extends MediaSitemap {
public static $template = 'video-sitemap';
/**
* Adding Google News Sitemap Headers
*/
public function extraSitemapHeader() {
return array( 'xmlns:video' => 'http://www.google.com/schemas/sitemap-video/1.1' );
}
public function add_urls( string $url, array $media ): void {
$videos = array();
foreach ( $media as $video ) {
$extensions = explode( '.', $video );
$extension = end( $extensions );
if ( 'video' === wp_ext2type( $extension ) ) {
$attachment_id = attachment_url_to_postid( $video );
if ( $attachment_id ) {
$thumbnail = get_the_post_thumbnail_url( $attachment_id, 'thumbnail' );
$metadata = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
$videos[] = array(
'thumbnail' => ! empty( $thumbnail ) ? $thumbnail : trailingslashit( includes_url() ) . 'images/media/video.png',
'title' => get_the_title( $attachment_id ),
'description' => wp_get_attachment_caption( $attachment_id ),
'player_loc' => $video,
'duration' => $metadata['length'] ?? '',
);
}
} elseif ( sgg_pro_enabled() && class_exists( 'SGG_PRO\Classes\Video_Sitemap' ) ) {
if ( ! empty( $this->settings->youtube_api_key ) && $this->is_youtube_url( $video ) ) {
$youtube_data = Video_Sitemap::get_youtube_data( $video, $this->settings->youtube_api_key, $this->settings->enable_video_api_cache );
if ( ! empty( $youtube_data ) ) {
$videos[] = $youtube_data;
}
} elseif ( ! empty( $this->settings->vimeo_api_key ) && $this->is_vimeo_url( $video ) ) {
$vimeo_data = Video_Sitemap::get_vimeo_data( $video, $this->settings->vimeo_api_key, $this->settings->enable_video_api_cache );
if ( ! empty( $vimeo_data ) ) {
$videos[] = $vimeo_data;
}
} elseif ( $this->is_twitter_url( $video ) ) {
$twitter_data = Video_Sitemap::get_twitter_data( $video, $this->settings->enable_video_api_cache );
if ( ! empty( $twitter_data ) ) {
$videos[] = $twitter_data;
}
}
}
}
if ( ! empty( $videos ) ) {
// Remove old URL if it exists
$this->urls = array_filter(
$this->urls,
function( $item ) use ( $url ) {
return $item[0] !== $url;
}
);
$this->urls[] = array(
$url, // URL
$videos, // Videos
);
}
}
public function filter_value( string $value ): bool {
$extensions = explode( '.', $value );
$extension = end( $extensions );
return 'video' === wp_ext2type( $extension )
|| ( sgg_pro_enabled() && (
$this->is_youtube_url( $value ) ||
$this->is_vimeo_url( $value ) ||
$this->is_twitter_url( $value )
) );
}
/**
* Detect a YouTube video URL
*/
public function is_youtube_url( $url ) {
return (
false !== strpos( $url, 'https://www.youtube.com/embed/' ) ||
false !== strpos( $url, 'https://youtu.be/' ) ||
false !== strpos( $url, 'https://www.youtube.com/watch?v=' ) ||
false !== strpos( $url, '//www.youtube.com/embed/' ) ||
false !== strpos( $url, '//youtu.be/' ) ||
false !== strpos( $url, '//www.youtube.com/watch?v=' )
);
}
/**
* Detect a Vimeo video URL
*/
public function is_vimeo_url( $url ) {
return (
false !== strpos( $url, 'https://vimeo.com/' ) ||
false !== strpos( $url, 'https://player.vimeo.com/video/' )
);
}
/**
* Detect a Twitter post URL
*/
public function is_twitter_url( $url ) {
return preg_match( '#https?://(?:www\.)?(?:twitter\.com|x\.com)/[^/]+/status/(\d+)#i', $url );
}
/**
* Detect an Instagram post, Reel or IGTV URL
*/
public function is_instagram_url( $url ) {
return preg_match( '#https?://(?:www\.)?instagram\.com/(?:p|reel|tv)/([A-Za-z0-9_-]+)/?#i', $url );
}
/**
* Detect a TikTok video URL (full or "vm." shortlink)
*/
public function is_tiktok_url( $url ): bool {
return (bool) preg_match( '~^https?://(?:www\.|m\.)?tiktok\.com/@[A-Za-z0-9._-]+/video/\d+(?:[/?].*)?$~i', $url )
|| (bool) preg_match( '~^https?://vm\.tiktok\.com/[A-Za-z0-9_-]+/?$~i', $url );
}
}

View File

@@ -0,0 +1,100 @@
<?php
namespace GRIM_SG;
class Wizard extends Dashboard {
public static $activation_redirect = 'sgg_activation_redirect';
private static $wizard_completed = 'sgg_wizard_completed';
public function __construct() {
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
add_action( 'admin_init', array( $this, 'maybe_redirect_to_wizard' ) );
add_action( 'wp_ajax_save_wizard_settings', array( $this, 'save_wizard_settings' ) );
}
public function add_admin_menu() {
add_submenu_page(
self::$slug,
esc_html__( 'Google XML Sitemaps Generator Wizard', 'xml-sitemap-generator-for-google' ),
esc_html__( 'Sitemaps Wizard', 'xml-sitemap-generator-for-google' ),
'manage_options',
$this->get_wizard_page_slug(),
array( $this, 'render_wizard_page' )
);
}
public function render_wizard_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
wp_enqueue_style( 'sgg-wizard-styles', GRIM_SG_URL . 'assets/css/wizard.min.css', array(), GRIM_SG_VERSION );
wp_enqueue_style( 'sgg-icons', GRIM_SG_URL . 'assets/fonts/icons/style.css', array(), GRIM_SG_VERSION );
wp_enqueue_script( 'sgg-wizard-scripts', GRIM_SG_URL . 'assets/js/wizard.js', array( 'jquery' ), GRIM_SG_VERSION, true );
wp_localize_script(
'sgg-wizard-scripts',
'sggWizard',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'sgg_wizard_nonce' ),
'continue' => esc_html__( 'Continue', 'xml-sitemap-generator-for-google' ),
'finish' => esc_html__( 'Finish', 'xml-sitemap-generator-for-google' ),
)
);
self::render(
'wizard/main.php',
array(
'settings' => $this->get_settings(),
)
);
}
public function maybe_redirect_to_wizard() {
if ( ! get_transient( self::$activation_redirect ) || ! current_user_can( 'manage_options' )
|| wp_doing_ajax() || is_network_admin() ) {
return;
}
delete_transient( self::$activation_redirect );
if ( ! get_option( self::$wizard_completed ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=' . $this->get_wizard_page_slug() ) );
exit;
}
}
public function save_wizard_settings() {
if ( ! current_user_can( 'manage_options' ) || ! wp_verify_nonce( $_POST['nonce'] ?? '', 'sgg_wizard_nonce' ) ) {
return;
}
$settings = $this->get_settings();
$settings->enable_sitemap = sanitize_text_field( $_POST['enable_sitemap'] ?? 0 );
$settings->enable_html_sitemap = sanitize_text_field( $_POST['enable_html_sitemap'] ?? 0 );
$settings->enable_google_news = sanitize_text_field( $_POST['enable_google_news'] ?? 0 );
$settings->enable_image_sitemap = sanitize_text_field( $_POST['enable_image_sitemap'] ?? 0 );
$settings->enable_video_sitemap = sanitize_text_field( $_POST['enable_video_sitemap'] ?? 0 );
$settings->sitemap_view = sanitize_text_field( $_POST['sitemap_view'] ?? '' );
$settings->enable_cache = sanitize_text_field( $_POST['enable_cache'] ?? 0 );
$settings->cache_timeout = sanitize_text_field( $_POST['cache_timeout'] ?? $settings->cache_timeout );
$settings->cache_timeout_period = sanitize_text_field( $_POST['cache_timeout_period'] ?? $settings->cache_timeout_period );
update_option( self::$slug, $settings );
flush_rewrite_rules();
wp_send_json(
array(
'success' => true,
'redirect' => admin_url( 'admin.php?page=' . self::$slug ),
)
);
}
public function get_wizard_page_slug() {
return self::$slug . '-wizard';
}
}

View File

@@ -0,0 +1,55 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Language Files
if ( ! is_textdomain_loaded( 'xml-sitemap-generator-for-google' ) ) {
load_plugin_textdomain( 'xml-sitemap-generator-for-google', false, 'xml-sitemap-generator-for-google/languages' );
}
// Autoload Files
require_once GRIM_SG_INCLUDES . 'hooks.php';
require_once GRIM_SG_INCLUDES . 'helpers.php';
require_once GRIM_SG_INCLUDES . 'search-settings.php';
// Autoload
require_once GRIM_SG_INCLUDES . 'vendor/Controller.php';
require_once GRIM_SG_INCLUDES . 'vendor/SitemapGenerator.php';
require_once GRIM_SG_INCLUDES . 'vendor/QueryBuilder.php';
require_once GRIM_SG_INCLUDES . 'vendor/PTSettings.php';
require_once GRIM_SG_INCLUDES . 'vendor/Settings.php';
require_once GRIM_SG_INCLUDES . 'vendor/Migration.php';
require_once GRIM_SG_INCLUDES . 'IndexNow.php';
require_once GRIM_SG_INCLUDES . 'Cache.php';
require_once GRIM_SG_INCLUDES . 'Sitemap.php';
require_once GRIM_SG_INCLUDES . 'Frontend.php';
require_once GRIM_SG_INCLUDES . 'GoogleNews.php';
require_once GRIM_SG_INCLUDES . 'MediaSitemap.php';
require_once GRIM_SG_INCLUDES . 'ImageSitemap.php';
require_once GRIM_SG_INCLUDES . 'VideoSitemap.php';
require_once GRIM_SG_INCLUDES . 'MultilingualSitemap.php';
require_once GRIM_SG_INCLUDES . 'Tools.php';
require_once GRIM_SG_INCLUDES . 'ImportExport.php';
require_once GRIM_SG_INCLUDES . 'PostSettings.php';
require_once GRIM_SG_INCLUDES . 'SitemapCLI.php';
function sgg_init() {
new GRIM_SG\Vendor\Migration();
new GRIM_SG\Frontend();
new GRIM_SG\Tools();
new GRIM_SG\PostSettings();
// WP Admin
if ( is_admin() ) {
require_once GRIM_SG_INCLUDES . 'Dashboard.php';
require_once GRIM_SG_INCLUDES . 'Notices.php';
require_once GRIM_SG_INCLUDES . 'Wizard.php';
new GRIM_SG\Dashboard();
new GRIM_SG\Notices();
new GRIM_SG\ImportExport();
new GRIM_SG\Wizard();
}
}
add_action( 'plugins_loaded', 'sgg_init', 1 );

View File

@@ -0,0 +1,174 @@
<?php
use GRIM_SG\ImageSitemap;
use GRIM_SG\VideoSitemap;
function sgg_pro_enabled() {
return defined( 'SGG_PRO_VERSION' );
}
function sgg_get_pro_url( $utm = 'buy-now' ) {
return "https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=sgg-plugin&utm_medium={$utm}&utm_campaign=xml_sitemap";
}
function sgg_get_support_url() {
return 'https://wordpress.org/support/plugin/xml-sitemap-generator-for-google/';
}
function sgg_get_review_url() {
return sgg_get_support_url() . 'reviews/?filter=5#new-post';
}
function sgg_show_pro_badge() {
if ( ! sgg_pro_enabled() ) {
load_template( GRIM_SG_PATH . '/templates/partials/pro-badge.php', false );
}
}
function sgg_show_pro_overlay( $args = array() ) {
if ( ! sgg_pro_enabled() ) {
load_template( GRIM_SG_PATH . '/templates/partials/pro-overlay.php', false, $args );
}
}
function sgg_pro_class() {
return sgg_pro_enabled() ? 'active' : 'inactive';
}
function sgg_parse_language( $lang ) {
$lang = str_replace( '_', '-', convert_chars( strtolower( strip_tags( $lang ) ) ) );
if ( 0 === strpos( $lang, 'zh' ) ) {
$lang = strpos( $lang, 'hk' ) || strpos( $lang, 'hant' ) || strpos( $lang, 'tw' ) ? 'zh-tw' : 'zh-cn';
} else {
$explode = explode( '-', $lang );
$lang = $explode[0];
}
return ! empty( $lang ) ? $lang : 'en';
}
function sgg_is_sitemap_index( $template, $settings = null ) {
if ( ! $settings ) {
$settings = ( new \GRIM_SG\Vendor\Controller() )->get_settings();
}
// Detect Media Sitemap Structure
if ( in_array( $template, array( ImageSitemap::$template, VideoSitemap::$template ), true ) && ! empty( $settings->sitemap_view ) ) {
$sitemap_structure = get_option( "sgg_{$template}_structure" );
return 'multiple' === $sitemap_structure;
}
return in_array( $template, array( 'sitemap', 'inner-sitemap' ), true ) && ! empty( $settings->sitemap_view );
}
function sgg_get_home_url( $path = '' ) {
$home_url = function_exists( 'pll_home_url' ) ? pll_home_url() : get_home_url();
$home_url = trim( apply_filters( 'wpml_home_urls', $home_url ), '/' );
if ( function_exists( 'trp_get_locale' ) ) {
$trp_settings = get_option( 'trp_settings' );
$current_locale = trp_get_locale();
if ( $current_locale !== $trp_settings['default-language'] ?? null ) {
$lang = substr( $current_locale, 0, 2 );
$home_url = get_site_url( null, $lang );
}
}
if ( defined( 'ICL_SITEPRESS_VERSION' ) && ! empty( $path ) && ! empty( $_GET['lang'] ) && false !== strpos( $home_url, '?lang=' ) ) {
$home_url = trim( strtok( $home_url, '?' ), '/' );
$home_url = add_query_arg( 'lang', sanitize_text_field( $_GET['lang'] ), "{$home_url}/{$path}" );
$path = ''; // Reset path to avoid duplication
}
$home_url = apply_filters( 'xml_sitemaps_site_url', $home_url );
return ! empty( $path ) ? "{$home_url}/{$path}" : $home_url;
}
function sgg_get_home_url_with_trailing_slash() {
return trailingslashit( untrailingslashit( sgg_get_home_url() ) );
}
function sgg_is_nginx() {
return isset( $_SERVER['SERVER_SOFTWARE'] ) && stristr( sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ), 'nginx' ) !== false;
}
function sgg_is_using_mod_rewrite() {
global $wp_rewrite;
return $wp_rewrite->using_mod_rewrite_permalinks();
}
function sgg_get_sitemap_url( $sitemap_url, $sitemap_type, $suffix = true ) {
if ( sgg_is_using_mod_rewrite() ) {
return sgg_get_home_url( $sitemap_url );
} else {
return sgg_get_home_url( "index.php?{$sitemap_type}" . ( $suffix ? '=true' : '' ) );
}
}
function sgg_get_languages( $with_default = false ) {
$languages = array();
if ( function_exists( 'pll_languages_list' ) ) {
$languages = pll_languages_list( array( 'fields' => 'slug' ) );
$default_lang = array_search( pll_default_language(), $languages, true );
if ( false !== $default_lang && ! $with_default ) {
unset( $languages[ $default_lang ] );
}
}
if ( function_exists( 'trp_get_languages' ) ) {
$trp_settings = get_option( 'trp_settings' );
$trp_slugs = $trp_settings['url-slugs'] ?? array();
if ( ! $with_default ) {
unset( $trp_slugs[ $trp_settings['default-language'] ?? '' ] );
}
$languages = array_values( $trp_slugs );
}
return $languages;
}
function sgg_get_default_language_code() {
if ( function_exists( 'pll_default_language' ) ) {
return pll_default_language();
}
return apply_filters( 'wpml_default_language', null );
}
function sgg_is_multilingual() {
return function_exists( 'pll_languages_list' )
|| function_exists( 'trp_get_languages' )
|| defined( 'ICL_SITEPRESS_VERSION' );
}
function sgg_maybe_remove_inner_suffix( $template ) {
if ( strpos( $template, '-inner-sitemap' ) !== false ) {
$template = str_replace( '-inner-sitemap', '', $template );
}
return $template;
}
function sgg_pro_features_page_tab( $tabs ) {
if ( ! sgg_pro_enabled() ) {
$tabs['xml_sitemap_generator_for_google_pro'] = sprintf(
'<a href="%s" target="_blank" class="sgg-plugin-pro-feature">%s</a>',
esc_url( 'https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=sgg-plugin&utm_medium=plugins&utm_campaign=xml_sitemap' ),
esc_html__( 'XML Sitemaps Generator Pro Features', 'xml-sitemap-generator-for-google' )
);
wp_enqueue_style( 'sgg-styles', GRIM_SG_URL . 'assets/css/styles.min.css', array(), GRIM_SG_VERSION );
}
return $tabs;
}
add_filter( 'install_plugins_tabs', 'sgg_pro_features_page_tab' );

View File

@@ -0,0 +1,234 @@
<?php
/**
* Plugin Activation Hook
*/
function sgg_activation() {
\GRIM_SG\Frontend::activate_plugin();
\GRIM_SG\Vendor\Migration::update_version();
( new \GRIM_SG\IndexNow() )->set_api_key();
update_option( 'sgg_installation_time', time(), false );
// Set the activation redirect transient.
set_transient( 'sgg_activation_redirect', true, MINUTE_IN_SECONDS );
}
/**
* Plugin Deactivation Hook
*/
function sgg_deactivation() {
\GRIM_SG\IndexNow::delete_api_key();
delete_option( 'sgg_installation_time' );
}
/**
* Get Polylang language for a post.
*/
function sgg_polylang_post_language( $language, $post_id ) {
if ( function_exists( 'pll_get_post_language' ) ) {
$language = pll_get_post_language( $post_id, 'slug' );
}
return $language;
}
add_filter( 'xml_sitemap_news_language', 'sgg_polylang_post_language', 10, 2 );
/**
* Get the WPML language for a post.
*/
function sgg_wpml_post_language( $language, $post_id, $post_type = 'post' ) {
global $sitepress;
if ( $sitepress ) {
$language = apply_filters(
'wpml_element_language_code',
$language,
array(
'element_id' => $post_id,
'element_type' => $post_type,
)
);
}
return $language;
}
add_filter( 'xml_sitemap_news_language', 'sgg_wpml_post_language', 10, 3 );
/**
* Exclude posts with noindex from the sitemap.
*/
function sgg_exclude_noindex_posts( $value, $post_id ) {
// Yoast SEO noindex
if ( defined( 'WPSEO_VERSION' ) && '1' === get_post_meta( $post_id, '_yoast_wpseo_meta-robots-noindex', true ) ) {
return false;
}
// Rank Math noindex
if ( class_exists( 'RankMath' ) ) {
$rank_math_robots = get_post_meta( $post_id, 'rank_math_robots', true );
if ( ! empty( $rank_math_robots ) && is_array( $rank_math_robots ) && in_array( 'noindex', $rank_math_robots, true ) ) {
return false;
}
}
// SEO Framework noindex
if ( defined( 'THE_SEO_FRAMEWORK_VERSION' ) ) {
$seo_framework_noindex = get_post_meta( $post_id, '_genesis_noindex', true );
if ( '1' === $seo_framework_noindex ) {
return false;
}
}
return $value;
}
add_filter( 'xml_sitemap_include_post', 'sgg_exclude_noindex_posts', 99, 2 );
/**
* Exclude terms with noindex from the sitemap.
*/
function sgg_exclude_noindex_terms( $value, $term_id, $taxonomy ) {
// Yoast SEO noindex
if ( is_callable( '\WPSEO_Taxonomy_Meta::get_term_meta' ) ) {
$noindex = \WPSEO_Taxonomy_Meta::get_term_meta( $term_id, $taxonomy, 'noindex' );
if ( 'noindex' === $noindex ) {
return true;
}
}
// Rank Math noindex
if ( class_exists( 'RankMath' ) ) {
$rank_math_robots = get_term_meta( $term_id, 'rank_math_robots', true );
if ( ! empty( $rank_math_robots ) && is_array( $rank_math_robots ) && in_array( 'noindex', $rank_math_robots, true ) ) {
return true;
}
}
// SEO Framework noindex
if ( defined( 'THE_SEO_FRAMEWORK_VERSION' ) ) {
$seo_framework_meta = get_term_meta( $term_id, 'autodescription-term-settings', true );
if ( ! empty( $seo_framework_meta ) && isset( $seo_framework_meta['noindex'] ) && 1 === $seo_framework_meta['noindex'] ) {
return true;
}
}
return $value;
}
add_filter( 'sgg_sitemap_exclude_single_term', 'sgg_exclude_noindex_terms', 99, 3 );
/**
* Add FooGallery image URLs to the sitemap.
*/
function sgg_add_foogallery_image_urls( $urls, $post_id ) {
if ( defined( 'FOOGALLERY_CPT_GALLERY' ) && class_exists( 'FooGallery' ) ) {
$content = get_post_field( 'post_content', $post_id );
if ( false !== strpos( $content, FOOGALLERY_CPT_GALLERY ) ) {
$gallery_ids = array();
preg_match_all( '/<!--\s*wp:fooplugins\/foogallery\s*{"id":\s*(\d+)\s*}\s*\/-->/', $content, $matches );
if ( ! empty( $matches[1] ) ) {
$gallery_ids = array_map( 'intval', $matches[1] );
}
if ( ! empty( $gallery_ids ) ) {
$gallery_ids = array_unique( $gallery_ids );
foreach ( $gallery_ids as $gallery_id ) {
$gallery = FooGallery::get_by_id( $gallery_id );
if ( $gallery ) {
foreach ( $gallery->attachments() as $attachment ) {
$urls[] = wp_get_attachment_url( $attachment->ID );
}
}
}
}
}
}
return $urls;
}
add_filter( 'sgg_sitemap_post_media_urls', 'sgg_add_foogallery_image_urls', 10, 2 );
/**
* BeeTheme Compatibility
*/
function sgg_be_theme_compatibility( $content, $post ) {
if ( defined( 'MFN_THEME_VERSION' ) ) {
$mfn_items = get_post_meta( $post->ID, 'mfn-builder-preview', true );
if ( ! empty( $mfn_items ) ) {
if ( ! is_array( $mfn_items ) ) {
$mfn_items = call_user_func( 'base64_decode', $mfn_items );
}
if ( ! empty( $mfn_items ) ) {
$content = is_array( $mfn_items ) ? implode( '', $mfn_items ) : $mfn_items;
}
}
}
return $content;
}
add_filter( 'xml_media_sitemap_post_content', 'sgg_be_theme_compatibility', 10, 2 );
/**
* Serve IndexNow API key.
*/
function sgg_serve_indexnow_api_key() {
global $wp;
$indexnow = new \GRIM_SG\IndexNow();
$current_url = home_url( $wp->request );
if ( ! empty( $current_url ) && $indexnow->get_api_key_location() === $current_url ) {
header( 'Content-Type: text/plain' );
header( 'X-Robots-Tag: noindex' );
status_header( 200 );
echo esc_html( $indexnow->get_api_key() );
exit();
}
}
add_action( 'wp', 'sgg_serve_indexnow_api_key' );
/**
* Clear Media Sitemap cache when a post status is changed.
*/
function sgg_clear_media_sitemap_cache( $new_status, $old_status, $post ) {
$settings = get_option( \GRIM_SG\Vendor\Controller::$slug );
if ( is_object( $settings ) && ! empty( $settings->disable_media_sitemap_cache ) ) {
return;
}
if ( ( 'publish' === $old_status && 'publish' !== $new_status )
|| ( 'publish' === $new_status && 'publish' !== $old_status ) ) {
\GRIM_SG\MediaSitemap::delete_all_cache();
}
}
add_action( 'transition_post_status', 'sgg_clear_media_sitemap_cache', 10, 3 );
/**
* Disable default WordPress Sitemaps.
*/
add_filter( 'wp_sitemaps_enabled', '__return_false' );
/**
* Google New Title Filter
*/
function sgg_google_news_title( $title, $post_id ) {
// SEO Framework title
if ( defined( 'THE_SEO_FRAMEWORK_VERSION' ) ) {
$seo_title = get_post_meta( $post_id, '_genesis_title', true );
if ( ! empty( $seo_title ) ) {
$title = $seo_title;
}
}
return $title;
}
add_filter( 'xml_sitemap_google_news_title', 'sgg_google_news_title', 10, 2 );

View File

@@ -0,0 +1,260 @@
<?php
function xml_sitemap_generate_settings() {
$settings_array = array(
'general' => array(
array(
'id' => 'sitemap_to_robots',
'label' => 'Add Sitemap Output URLs to site "robots.txt" file',
'tags' => 'robots.txt',
),
array(
'id' => 'enable_indexnow',
'label' => 'Enable IndexNow Protocol (Microsoft Bing, Seznam.cz, Naver, Yandex)',
'tags' => 'Posts',
),
array(
'id' => 'enable_sitemap',
'label' => 'XML Sitemap',
),
array(
'id' => 'enable_html_sitemap',
'label' => 'HTML Sitemap',
),
array(
'id' => 'webserver_configuration',
'label' => 'Webserver Configuration' ,
),
array(
'id' => 'sitemap_structure',
'label' => 'Sitemap Structure' ,
),
array(
'id' => 'links_per_page',
'label' => 'Links per page:' ,
),
array(
'id' => 'custom_sitemaps',
'label' => 'Custom Sitemaps' ,
),
array(
'id' => 'additional_urls',
'label' => 'Additional URLs',
),
array(
'id' => 'general_exclude_posts',
'label' => 'Exclude',
),
array(
'id' => 'general_include_only_terms',
'label' => 'Include only selected Terms',
),
array(
'id' => 'posts_priority',
'label' => 'Posts Priority',
),
array(
'id' => 'sitemap_options',
'label' => 'Sitemap Options',
),
array(
'id' => 'general_custom_post_types',
'label' => 'General Custom Post Types',
),
),
'google-news' => array(
array(
'id' => 'enable_google_news',
'label' => 'Google News',
'tags' => '',
),
array(
'id' => 'google_news_name',
'label' => 'Publication Name',
),
array(
'id' => 'google_news_old_posts',
'label' => 'Include Older Posts',
),
array(
'id' => 'google__url',
'label' => 'Google News URL',
),
array(
'id' => 'google_keywords',
'label' => 'Keywords',
),
array(
'id' => 'google_news_stocks',
'label' => 'Stock Tickers',
),
array(
'id' => 'google_exclude',
'label' => 'Exclude',
),
array(
'id' => 'google_include',
'label' => 'Include only selected Terms',
),
array(
'id' => 'google_content_post',
'label' => 'Content Options',
),
array(
'id' => 'google_custom_post_types',
'label' => 'Google Custom Post Types',
),
),
'image-sitemap' => array(
array(
'id' => 'enable_image_sitemap',
'label' => 'Image Sitemap',
),
array(
'id' => 'image_sitemap_url',
'label' => 'Image Sitemap URL:',
),
array(
'id' => 'hide_image_previews',
'label' => 'Hide Image Previews',
),
array(
'id' => 'hide_image_sitemap_xsl',
'label' => 'Hide XSL Template',
),
array(
'id' => 'image_mime_types',
'label' => 'Image MIME Types',
),
array(
'id' => 'exclude_broken_images',
'label' => 'Exclude Broken Images',
),
array(
'id' => 'include_featured_images',
'label' => 'Include Featured Images',
),
array(
'id' => 'include_woo_gallery',
'label' => 'Include WooCommerce Gallery Images',
),
array(
'id' => 'image_content_option',
'label' => 'Content Options',
),
array(
'id' => 'image_custom_post_types',
'label' => 'Image Custom Post Types',
),
),
'video-sitemap' => array(
array(
'id' => 'enable_video_sitemap',
'label' => 'Enable Video Sitemap',
),
array(
'id' => 'video_sitemap_url',
'label' => 'Video Sitemap URL:',
),
array(
'id' => 'hide_video_sitemap_xsl',
'label' => 'Hide XSL Template',
),
array(
'id' => 'sgg_youtube',
'label' => 'YouTube',
),
array(
'id' => 'youtube_api_key',
'label' => 'YouTube Data API v3 Key:',
),
array(
'id' => 'sgg_vimeo',
'label' => 'Vimeo',
),
array(
'id' => 'vimeo_check_api_key',
'label' => 'Vimeo Access Token:',
),
array(
'id' => 'enable_video_api_cache',
'label' => 'API Data Cache',
),
array(
'id' => 'video_content_option',
'label' => 'Content Options',
),
array(
'id' => 'video_custom_post_types',
'label' => 'Custom Post Types',
),
),
'advanced' => array(
array(
'id' => 'enable_cache',
'label' => 'Cache',
),
array(
'id' => 'cache_timeout_period',
'label' => 'Cache Expiration Time:',
),
array(
'id' => 'last_cached_time',
'label' => 'Last Cached Time:',
),
array(
'id' => 'clear_cache',
'label' => 'Clear Cache',
),
array(
'id' => 'clear_cache_on_save_post',
'label' => 'Smart Caching',
),
array(
'id' => 'disable_media_sitemap_cache',
'label' => 'Disable Media Sitemap Cache Collection',
),
array(
'id' => 'minimize_sitemap',
'label' => 'Minimize Sitemap source code',
),
array(
'id' => 'advanced_sitemap_styles',
'label' => 'Sitemap Styles',
),
array(
'id' => 'hide_branding',
'label' => 'Hide Branding Marks',
),
array(
'id' => 'enable_cronjob',
'label' => 'Cron Job',
),
array(
'id' => 'cronjob_runtime',
'label' => 'Cron Job Run Time:',
),
array(
'id' => 'advanced_wp_cli',
'label' => 'WP CLI',
),
array(
'id' => 'advanced_import_settings',
'label' => 'Import Settings',
),
array(
'id' => 'advanced_export_settings',
'label' => 'Export Settings',
),
),
);
$flat_settings_array = array();
foreach ( $settings_array as $tab => $settings ) {
foreach ( $settings as $setting ) {
$setting['tab'] = $tab;
$flat_settings_array[] = $setting;
}
}
return $flat_settings_array;
}

View File

@@ -0,0 +1,87 @@
<?php
namespace GRIM_SG\Vendor;
use GRIM_SG\Settings;
class Controller {
public static $slug = 'xml-sitemap-generator-for-google';
public function get_settings() {
$settings = new Settings();
$saved_options = get_option( self::$slug );
// TODO Remove this after Refactoring
if ( is_array( $saved_options ) ) {
$saved_options = (object) $saved_options;
}
if ( ! empty( $saved_options ) ) {
foreach ( $settings as $key => &$option ) {
if ( isset( $saved_options->{$key} ) ) {
if ( in_array( $key, array( 'cpt', 'taxonomies' ), true ) ) {
if ( is_array( $saved_options->{$key} ) ) {
foreach ( $saved_options->{$key} as $inner_key => $value ) {
$option[ $inner_key ] = is_array( $value )
? (object) $value // TODO Remove this after Refactoring
: $value;
}
}
} else {
$option = ( is_object( $option ) && is_array( $saved_options->{$key} ) )
? (object) $saved_options->{$key} // TODO Remove this after Refactoring
: $saved_options->{$key};
}
}
}
}
return $settings;
}
/**
* Get Custom Post Types
* @return string[]|\WP_Post_Type[]
*/
public function get_cpt( $output = 'names' ) {
$args = array(
'public' => true,
'_builtin' => false,
);
return get_post_types( $args, $output );
}
/**
* Get Taxonomy Types
* @return string[]|\WP_Taxonomy[]
*/
public function get_taxonomy_types( $output = 'names' ) {
$args = array(
'public' => true,
'show_ui' => true,
);
return get_taxonomies( $args, $output );
}
/**
* Get Allowed Post Types List
* @return array
*/
public function get_post_types_list( $post_types, $settings ) {
foreach ( $post_types as $key => $post_type ) {
if ( isset( $settings->{$post_type}->include ) && ! $settings->{$post_type}->include ) {
unset( $post_types[ $key ] );
}
}
foreach ( $this->get_cpt() as $cpt ) {
if ( ! empty( $settings->cpt[ $cpt ] ) && ! empty( $settings->cpt[ $cpt ]->include ) ) {
$post_types[] = $cpt;
}
}
return $post_types;
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace GRIM_SG\vendor;
class Migration extends Controller {
const DB_VERSION_KEY = 'sgg_version';
/**
* Database updates and callbacks that need to be run per Migration version.
*/
private $migrations = array(
'1.8.4' => array(
'migrate_settings_dynamic_created_objects',
),
'1.9.9' => array(
'migrate_video_settings',
),
);
public function __construct() {
add_action( 'admin_init', array( $this, 'run_migrations' ) );
}
/**
* Runs all the necessary migrations.
*/
public function run_migrations() {
$current_db_version = get_option( self::DB_VERSION_KEY, '' );
if ( version_compare( $current_db_version, GRIM_SG_VERSION, '>=' ) ) {
return;
}
foreach ( $this->migrations as $version => $update_callbacks ) {
if ( version_compare( $current_db_version, $version, '<' ) ) {
foreach ( $update_callbacks as $update_callback ) {
$this->{$update_callback}();
}
}
}
self::update_version();
}
/**
* Update Version in Database
*/
public static function update_version() {
update_option( self::DB_VERSION_KEY, GRIM_SG_VERSION );
}
/**
* Migrate Dynamic created CPT and Taxonomies to array
*/
public function migrate_settings_dynamic_created_objects() {
$settings = get_option( self::$slug, array() );
if ( ! empty( $settings ) ) {
$settings->cpt = array();
$settings->taxonomies = array();
foreach ( $this->get_cpt() as $cpt ) {
if ( ! empty( $settings->{$cpt} ) ) {
$settings->cpt[ $cpt ] = $settings->{$cpt};
}
}
foreach ( $this->get_taxonomy_types() as $taxonomy ) {
if ( ! empty( $settings->{$taxonomy} ) ) {
$settings->taxonomies[ $taxonomy ] = $settings->{$taxonomy};
}
}
update_option( Controller::$slug, $settings );
}
}
/**
* Migrate Video Sitemap Settings
*/
public function migrate_video_settings() {
$settings = get_option( self::$slug, array() );
if ( ! empty( $settings ) ) {
$settings->enable_video_api_cache = $settings->enable_youtube_cache ?? true;
update_option( Controller::$slug, $settings );
}
// Migrate YouTube Data to Video API Data
$youtube_data = get_option( 'sgg_youtube_data', array() );
if ( ! empty( $youtube_data ) ) {
update_option( 'sgg_video_api_data', $youtube_data );
}
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace GRIM_SG;
class PTSettings {
public $include = true;
public $priority = 3;
public $frequency = 'weekly';
public $google_news = false;
public $image_sitemap = true;
public $video_sitemap = true;
// Frequencies
public static $ALWAYS = 'always';
public static $HOURLY = 'hourly';
public static $DAILY = 'daily';
public static $WEEKLY = 'weekly';
public static $MONTHLY = 'monthly';
public static $YEARLY = 'yearly';
public static $NEVER = 'never';
/**
* DefaultSettings constructor.
*
* @param int $priority
* @param int $frequency
*/
public function __construct( $priority = 3, $frequency = 1, $google_news = false, $image_sitemap = false, $video_sitemap = false ) {
$this->priority = $priority;
$this->frequency = $frequency;
$this->google_news = $google_news;
$this->image_sitemap = $image_sitemap;
$this->video_sitemap = $video_sitemap;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace GRIM_SG\Vendor;
class QueryBuilder {
/**
* Run SQL Query
*
* @param $sql
* @return array|null|object
*/
public static function run_query( $sql ) {
global $wpdb;
return $wpdb->get_results( $sql );
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace GRIM_SG;
use GRIM_SG\Vendor\Controller;
class Settings extends Controller {
// Global Settings
public $sitemap_url = 'sitemap.xml';
public $html_sitemap_url = 'sitemap.html';
public $enable_sitemap = true;
public $links_per_page = 1000;
public $enable_html_sitemap = false;
public $sitemap_to_robots = true;
public $enable_indexnow = true;
public $sitemap_view = 'sitemap-index';
// Sitemap Data Settings
public $home;
public $page;
public $post;
public $archive;
public $archive_older;
public $authors;
public $media;
public $exclude_posts;
public $exclude_terms;
public $include_only_terms;
public $posts_priority;
public $custom_sitemaps = array();
public $additional_pages = array();
public $cpt = array();
public $taxonomies = array();
// Google News Data Settings
public $enable_google_news = false;
public $google_news_old_posts = false;
public $google_news_name = '';
public $google_news_url = 'google-news.xml';
public $google_news_keywords = '';
public $google_news_stocks = false;
public $google_news_exclude;
public $google_news_exclude_terms;
public $google_news_include_only_terms;
// Media Sitemap Data Settings
public $enable_image_sitemap = false;
public $enable_video_sitemap = false;
public $image_sitemap_url = 'image-sitemap.xml';
public $video_sitemap_url = 'video-sitemap.xml';
public $hide_image_previews = false;
public $hide_image_sitemap_xsl = false;
public $hide_video_sitemap_xsl = false;
public $image_mime_types = array(
'image/jpeg' => true,
'image/png' => true,
'image/gif' => true,
'image/bmp' => true,
'image/webp' => true,
'image/avif' => true,
);
public $youtube_api_key = '';
public $vimeo_api_key = '';
public $exclude_broken_images = false;
public $include_featured_images = false;
public $include_woo_gallery = false;
// Cache Settings
public $enable_cache = false;
public $cache_timeout = 24;
public $cache_timeout_period = 3600;
public $clear_cache_on_save_post = false;
public $enable_video_api_cache = true;
public $disable_media_sitemap_cache = false;
public $minimize_sitemap = false;
public $hide_branding = true;
public $enable_cronjob = false;
public $cronjob_runtime = 'daily';
public $colors = array(
'header_background_color' => '#82a745',
'header_text_color' => '#ffffff',
'sitemap_background_color' => '#ecf4db',
'sitemap_text_color' => '#444444',
'sitemap_link_color' => '#2d89c7',
'footer_text_color' => '#666666',
);
/**
* Settings constructor.
*/
public function __construct() {
$this->home = new PTSettings( 10, PTSettings::$DAILY );
$this->page = new PTSettings( 6, PTSettings::$WEEKLY, false, true, true );
$this->post = new PTSettings( 6, PTSettings::$MONTHLY, true, true, true );
$this->archive = new PTSettings( 6, PTSettings::$DAILY );
$this->archive_older = new PTSettings( 3, PTSettings::$YEARLY );
$this->authors = new PTSettings( 3, PTSettings::$WEEKLY );
$this->media = new PTSettings( 3, PTSettings::$WEEKLY );
// Media Pages are disabled by default
$this->media->include = false;
foreach ( $this->get_cpt() as $cpt ) {
$this->cpt[ $cpt ] = new PTSettings( 6, PTSettings::$MONTHLY );
}
foreach ( $this->get_taxonomy_types() as $taxonomy ) {
$this->taxonomies[ $taxonomy ] = new PTSettings( 3, PTSettings::$WEEKLY );
}
}
/**
* Get Default Settings
* @param $option
* @return PTSettings
*/
public function get_row_value( $option ) {
$settings = new PTSettings();
$settings->include = isset( $_POST[ $option . '_include' ] ) ? sanitize_text_field( $_POST[ $option . '_include' ] ) : false;
$settings->priority = isset( $_POST[ $option . '_priority' ] ) ? sanitize_text_field( $_POST[ $option . '_priority' ] ) : 0;
$settings->frequency = isset( $_POST[ $option . '_frequency' ] ) ? sanitize_text_field( $_POST[ $option . '_frequency' ] ) : $settings->frequency;
$settings->google_news = isset( $_POST[ $option . '_google_news' ] ) ? sanitize_text_field( $_POST[ $option . '_google_news' ] ) : 0;
$settings->image_sitemap = isset( $_POST[ $option . '_image_sitemap' ] ) ? sanitize_text_field( $_POST[ $option . '_image_sitemap' ] ) : 0;
$settings->video_sitemap = isset( $_POST[ $option . '_video_sitemap' ] ) ? sanitize_text_field( $_POST[ $option . '_video_sitemap' ] ) : 0;
return $settings;
}
}

View File

@@ -0,0 +1,636 @@
<?php
namespace GRIM_SG\Vendor;
use GRIM_SG\GoogleNews;
use GRIM_SG\ImageSitemap;
use GRIM_SG\MultilingualSitemap;
use GRIM_SG\VideoSitemap;
class SitemapGenerator {
public $sitemapFileName = 'sitemap.xml';
public $sitemapIndexFileName = 'sitemap-index.xml';
public $robotsFileName = 'robots.txt';
public $maxURLsPerSitemap = 50000;
public $createGZipFile = false;
private $baseURL;
private $searchEngines = array(
array(
'https://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=USERID&url=',
'https://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=',
),
'https://www.google.com/webmasters/tools/ping?sitemap=',
'https://submissions.ask.com/ping?sitemap=',
'https://www.bing.com/webmaster/ping.aspx?siteMap=',
);
private $urls = array();
private $sitemaps;
private $sitemapIndex;
private $sitemapFullURL;
/**
* Constructor.
*
* @param string $baseURL You site URL, with / at the end.
*/
public function __construct( $baseURL ) {
$this->baseURL = $baseURL;
}
public function addUrls( $urls_array, $callback = 'addUrl', $template = 'sitemap' ) {
if ( ! is_array( $urls_array ) ) {
throw new \InvalidArgumentException( 'Array as argument should be given.' );
}
if ( sgg_is_sitemap_index( $template ) ) {
foreach ( $urls_array as $sitemap => $inner_urls ) {
foreach ( $inner_urls as $url ) {
$this->{$callback}( $url, $sitemap );
}
}
} else {
foreach ( $urls_array as $url ) {
$this->{$callback}( $url );
}
}
}
/**
* Use this to add single URL to Google News Sitemap.
*/
public function addNewsUrl( $item ) {
$url = $item[0] ?? null;
$this->validateUrl( $url );
$tmp = array();
$tmp['loc'] = $url;
$tmp['publication_name'] = $item[1] ?? null;
$tmp['language'] = $item[2] ?? null;
$tmp['title'] = $item[3] ?? null;
if ( isset( $item[4] ) ) {
$tmp['lastmod'] = $item[4];
}
if ( sgg_pro_enabled() ) {
$tmp['keywords'] = implode( ', ', apply_filters( 'sgg_news_keywords', array(), $item[5] ?? null ) );
$tmp['stock_tickers'] = implode( ', ', apply_filters( 'sgg_news_stock_tickers', array(), $item[5] ?? null ) );
}
$this->urls[] = $tmp;
}
/**
* Use this to add single URL to Sitemap.
*/
public function addMediaUrl( $item, $sitemap = null ) {
$url = $item[0] ?? null;
$this->validateUrl( $url );
$tmp = array();
$tmp['loc'] = $url;
if ( isset( $item[1] ) ) {
$tmp['media'] = $item[1];
}
if ( ! empty( $sitemap ) ) {
$tmp['lastmod'] = gmdate( 'c' );
$this->urls[ $sitemap ][] = $tmp;
} else {
$this->urls[] = $tmp;
}
}
/**
* Use this to add single URL to Sitemap.
*/
public function addUrl( $item, $sitemap = null ) {
$url = $item[0] ?? null;
$this->validateUrl( $url );
$tmp = array();
$tmp['loc'] = $url;
if ( isset( $item[1] ) ) {
$tmp['lastmod'] = $item[1];
}
if ( isset( $item[2] ) ) {
$tmp['changefreq'] = $item[2];
}
if ( isset( $item[3] ) ) {
$tmp['priority'] = $item[3];
}
if ( ! empty( $sitemap ) ) {
$this->urls[ $sitemap ][] = $tmp;
} else {
$this->urls[] = $tmp;
}
}
/**
* Validate Sitemap Item URL
*/
public function validateUrl( $url ) {
if ( null === $url ) {
throw new \InvalidArgumentException( 'URL is mandatory. At least one argument should be given.' );
}
$urlLenght = extension_loaded( 'mbstring' ) ? mb_strlen( $url ) : strlen( $url );
if ( $urlLenght > 2048 ) {
throw new \InvalidArgumentException(
"URL lenght can't be bigger than 2048 characters.
Note, that precise url length check is guaranteed only using mb_string extension.
Make sure Your server allow to use mbstring extension."
);
}
}
/**
* Create sitemap in memory.
*/
public function createSitemap( $template = 'sitemap', $headers = array(), $is_xml = true ) {
if ( ! isset( $this->urls ) ) {
throw new \BadMethodCallException( 'To create sitemap, call addUrl or addUrls function first.' );
}
if ( $this->maxURLsPerSitemap > 50000 ) {
throw new \InvalidArgumentException( 'More than 50,000 URLs per single sitemap is not allowed.' );
}
$settings = ( new Controller() )->get_settings();
$stylesheet_template = sgg_maybe_remove_inner_suffix( $template );
$stylesheet_path = apply_filters( 'sitemap_xsl_template_path', 'sitemap-stylesheet.xsl' );
$stylesheet_url = sgg_get_sitemap_url( "{$stylesheet_path}?template={$stylesheet_template}", "sitemap_xsl={$stylesheet_template}", false );
$stylesheet_url = strtok( $stylesheet_url, '&' ); // remove & query string
$is_sitemap_index = sgg_is_sitemap_index( $template, $settings );
$is_media_template = in_array( $template, array( 'image-sitemap', 'video-sitemap' ), true );
$is_index_template = $is_media_template || 'sitemap' === $template;
$sitemap_urls = $is_sitemap_index
? $this->urls
: array_chunk( $this->urls, $this->maxURLsPerSitemap );
foreach ( $sitemap_urls as $sitemap_key => $sitemap ) {
$dom = $this->create_sitemap_dom( $stylesheet_url, $template, $settings );
$urlset = $this->create_sitemap_urlset( $dom, $headers );
$dom->appendChild( $urlset );
foreach ( $sitemap as $url ) {
$url_element = $dom->createElement( 'url' );
$url_element->appendChild(
$dom->createElement( 'loc', htmlspecialchars( $url['loc'], ENT_QUOTES, 'UTF-8' ) )
);
if ( GoogleNews::$template === $template ) {
if ( $settings->google_news_old_posts && GoogleNews::is_older_than_48h( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
} else {
$news = $url_element->appendChild( $dom->createElement( 'news:news' ) );
if ( isset( $url['publication_name'] ) ) {
$publication = $dom->createElement( 'news:publication' );
$news->appendChild( $publication );
$publication->appendChild(
$dom->createElement( 'news:name', esc_html( $url['publication_name'] ) )
);
$publication->appendChild(
$dom->createElement( 'news:language', $url['language'] )
);
}
if ( isset( $url['lastmod'] ) ) {
$news->appendChild(
$dom->createElement( 'news:publication_date', $url['lastmod'] )
);
}
if ( isset( $url['title'] ) ) {
$news->appendChild(
$dom->createElement( 'news:title', esc_html( $url['title'] ) )
);
}
if ( sgg_pro_enabled() ) {
$news->appendChild(
$dom->createElement( 'news:keywords', $url['keywords'] )
);
$news->appendChild(
$dom->createElement( 'news:stock_tickers', $url['stock_tickers'] )
);
}
}
} elseif ( strpos( $template, ImageSitemap::$template ) !== false ) {
if ( isset( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
} else {
if ( ! empty( $url['media'] ) ) {
foreach ( $url['media'] as $image ) {
$image_element = $url_element->appendChild( $dom->createElement( 'image:image' ) );
$image_element->appendChild(
$dom->createElement( 'image:loc', $image )
);
}
}
}
} elseif ( strpos( $template, VideoSitemap::$template ) !== false ) {
if ( isset( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
} else {
if ( ! empty( $url['media'] ) ) {
foreach ( $url['media'] as $video ) {
$video_element = $url_element->appendChild( $dom->createElement( 'video:video' ) );
$video_element->appendChild(
$dom->createElement( 'video:thumbnail_loc', esc_url( $video['thumbnail'] ?? '' ) )
);
// Decode HTML entities first, then DOMDocument will handle XML escaping properly
$video_title = html_entity_decode( $video['title'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8' );
$video_element->appendChild(
$dom->createElement( 'video:title', $video_title )
);
// Decode HTML entities first, then DOMDocument will handle XML escaping properly
$video_description = html_entity_decode( $video['description'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8' );
$video_element->appendChild(
$dom->createElement( 'video:description', $video_description )
);
$video_element->appendChild(
$dom->createElement( 'video:player_loc', esc_url( $video['player_loc'] ?? '' ) )
);
// Decode HTML entities first, then DOMDocument will handle XML escaping properly
$video_duration = html_entity_decode( $video['duration'] ?? '', ENT_QUOTES | ENT_HTML5, 'UTF-8' );
$video_element->appendChild(
$dom->createElement( 'video:duration', $video_duration )
);
}
}
}
} else {
if ( isset( $url['lastmod'] ) ) {
$url_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] )
);
}
if ( isset( $url['changefreq'] ) ) {
$url_element->appendChild(
$dom->createElement( 'changefreq', $url['changefreq'] )
);
}
if ( isset( $url['priority'] ) ) {
$url_element->appendChild(
$dom->createElement( 'priority', $url['priority'] )
);
}
}
$urlset->appendChild( $url_element );
if ( $is_sitemap_index && $is_index_template ) {
$this->sitemaps[ $sitemap_key ][] = array(
'loc' => $url['loc'],
'lastmod' => $url['lastmod'],
);
}
}
if ( ! sgg_pro_enabled() || ! $settings->minimize_sitemap ) {
$dom->formatOutput = true;
}
if ( ! $is_index_template || ! $is_sitemap_index ) {
$ready_sitemap = $dom->saveXML();
if ( $is_sitemap_index ) {
$this->sitemaps[ $sitemap_key ][] = $ready_sitemap;
$this->sitemaps[ $sitemap_key ]['lastmod'] = $url['lastmod'] ?? gmdate( 'c' );
} else {
$this->sitemaps[] = $ready_sitemap;
}
}
}
if ( null === $this->sitemaps ) {
$dom = $this->create_sitemap_dom( $stylesheet_url, $template, $settings );
$urlset = $this->create_sitemap_urlset( $dom, $headers );
$dom->appendChild( $urlset );
$this->sitemaps[] = $dom->saveXML();
}
if ( count( $this->sitemaps ) > 1000 ) {
throw new \LengthException( 'Sitemap index can contains 1000 single sitemaps. Perhaps You trying to submit too many URLs.' );
}
$is_media_index = $is_media_template && $is_sitemap_index;
if ( ! empty( $settings->sitemap_view ) && ( ( 'sitemap' === $template && count( $this->sitemaps ) > 0 ) || $is_media_index ) ) {
$stylesheet_url = sgg_get_sitemap_url( "{$stylesheet_path}?template=sitemap-index", 'sitemap_xsl=sitemap-index', false );
$stylesheet_url = strtok( $stylesheet_url, '&' ); // remove & query string
$dom = $this->create_sitemap_dom( $stylesheet_url, $template, $settings );
$sitemapindex = $dom->createElement( 'sitemapindex' );
$sitemapindex->setAttribute( 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance' );
$sitemapindex->setAttribute( 'xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd' );
$sitemapindex->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
$dom->appendChild( $sitemapindex );
foreach ( $this->sitemaps as $sitemap_key => $sitemap ) {
if ( ! empty( $sitemap ) && is_array( $sitemap ) ) {
if ( 'page' === $sitemap_key && sgg_get_home_url_with_trailing_slash() === ( $sitemap[0]['loc'] ?? '' ) && 1 < count( $sitemap ) ) {
$sitemap[0] = array(
'loc' => $sitemap[0]['loc'],
'lastmod' => max( $sitemap[0]['lastmod'] ?? '', $sitemap[1]['lastmod'] ?? '' ),
);
if ( ! empty( $sitemap[1] ) ) {
unset( $sitemap[1] );
}
$sitemap = array_values( $sitemap );
}
foreach ( $sitemap as $index => $url ) {
$sitemap_element = $dom->createElement( 'sitemap' );
$sitemap_type = $is_xml ? 'xml' : 'html';
$default_number = $is_media_template ? 1 : '';
$sitemap_number = 0 < $index ? intval( $index ) + 1 : $default_number;
$page_param = 0 < $sitemap_number ? "&page={$sitemap_number}" : '';
$sitemap_element->appendChild(
$dom->createElement(
'loc',
esc_url( sgg_get_sitemap_url( "{$sitemap_key}-sitemap{$sitemap_number}.{$sitemap_type}", "sitemap_{$sitemap_type}=true&inner_sitemap={$sitemap_key}{$page_param}", false ) )
)
);
$sitemap_element->appendChild(
$dom->createElement( 'lastmod', $url['lastmod'] ?? gmdate( 'c' ) )
);
$sitemapindex->appendChild( $sitemap_element );
}
}
}
if ( $is_xml && 'sitemap' === $template ) {
$additional_sitemaps = apply_filters( 'sgg_additional_index_sitemaps', $settings->custom_sitemaps ?? array() );
if ( $settings->enable_image_sitemap ) {
$additional_sitemaps[] = array(
'url' => sgg_get_sitemap_url( $settings->image_sitemap_url, 'image_sitemap' ),
);
}
if ( $settings->enable_video_sitemap ) {
$additional_sitemaps[] = array(
'url' => sgg_get_sitemap_url( $settings->video_sitemap_url, 'video_sitemap' ),
);
}
foreach ( $additional_sitemaps as $additional_sitemap ) {
$sitemap_element = $dom->createElement( 'sitemap' );
$sitemap_url = ! empty( $additional_sitemap['url'] ) ? esc_url( $additional_sitemap['url'] ) : $additional_sitemap;
if ( ! is_string( $sitemap_url ) ) {
continue;
}
$sitemap_element->appendChild(
$dom->createElement( 'loc', $sitemap_url )
);
$sitemap_element->appendChild(
$dom->createElement(
'lastmod',
! empty( $additional_sitemap['lastmod'] ) ? $additional_sitemap['lastmod'] : gmdate( 'c' )
)
);
$sitemapindex->appendChild( $sitemap_element );
}
}
if ( ! sgg_pro_enabled() || ! $settings->minimize_sitemap ) {
$dom->formatOutput = true;
}
$this->sitemapFullURL = $this->baseURL . $this->sitemapIndexFileName;
$this->sitemapIndex = array(
$this->sitemapIndexFileName,
$dom->saveXML(),
);
} else {
if ( $this->createGZipFile ) {
$this->sitemapFullURL = $this->baseURL . $this->sitemapFileName . '.gz';
} else {
$this->sitemapFullURL = $this->baseURL . $this->sitemapFileName;
}
if ( ! empty( $this->sitemaps[0] ) ) {
$this->sitemaps[0] = array(
$this->sitemapFileName,
$this->sitemaps[0],
);
}
}
}
/**
* Create Multilingual Sitemap in memory.
*/
public function createMultilingualSitemap( $urls = array(), $is_xml = true ) {
if ( ! isset( $this->urls ) ) {
throw new \BadMethodCallException( 'To create sitemap, call addUrl or addUrls function first.' );
}
if ( $this->maxURLsPerSitemap > 50000 ) {
throw new \InvalidArgumentException( 'More than 50,000 URLs per single sitemap is not allowed.' );
}
$stylesheet_path = apply_filters( 'sitemap_xsl_template_path', 'sitemap-stylesheet.xsl' );
$settings = ( new Controller() )->get_settings();
$dom = $this->create_sitemap_dom(
sgg_get_sitemap_url( "{$stylesheet_path}?template=multilingual-sitemap", 'sitemap_xsl=sitemap-index', false ),
'',
$settings
);
$sitemapindex = $dom->createElement( 'sitemapindex' );
$sitemapindex->setAttribute( 'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance' );
$sitemapindex->setAttribute( 'xsi:schemaLocation', 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd' );
$sitemapindex->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
$dom->appendChild( $sitemapindex );
foreach ( $urls as $url ) {
$sitemap_element = $dom->createElement( 'sitemap' );
$sitemap_element->appendChild(
$dom->createElement(
'loc',
esc_url( $url )
)
);
$sitemap_element->appendChild(
$dom->createElement( 'lastmod', gmdate( DATE_W3C ) )
);
$sitemapindex->appendChild( $sitemap_element );
}
if ( ! sgg_pro_enabled() || ! $settings->minimize_sitemap ) {
$dom->formatOutput = true;
}
$this->sitemapFullURL = $this->baseURL . $this->sitemapIndexFileName;
$this->sitemapIndex = array(
$this->sitemapIndexFileName,
$dom->saveXML(),
);
}
public function create_sitemap_dom( $stylesheet_url, $template = '', $settings = null ) {
$generator_info = 'sitemap-generator-url="https://wpgrim.com" sitemap-generator-version="' . GRIM_SG_VERSION . '"';
$dom = new \DOMDocument( '1.0', 'UTF-8' );
// Get settings if not provided
if ( null === $settings ) {
$settings = ( new Controller() )->get_settings();
}
// Skip XSL stylesheet reference based on settings
$is_index_sitemap = strpos( $stylesheet_url, 'sitemap-index' ) !== false;
$skip_xsl = false;
if ( ! $is_index_sitemap ) {
if ( strpos( $template, VideoSitemap::$template ) !== false ) {
$skip_xsl = ! empty( $settings->hide_video_sitemap_xsl );
} elseif ( strpos( $template, ImageSitemap::$template ) !== false ) {
$skip_xsl = ! empty( $settings->hide_image_sitemap_xsl );
}
}
if ( ! $skip_xsl ) {
$dom->appendChild(
$dom->createProcessingInstruction(
'xml-stylesheet',
'type="text/xsl" href="' . $stylesheet_url . '"'
)
);
}
$dom->appendChild( $dom->createComment( $generator_info ) );
return $dom;
}
public function create_sitemap_urlset( $dom, $headers = array() ) {
$urlset = $dom->createElement( 'urlset' );
$urlset->setAttribute( 'xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9' );
if ( ! empty( $headers ) ) {
foreach ( $headers as $key => $header ) {
$urlset->setAttribute( $key, $header );
}
}
return $urlset;
}
/**
* Returns created sitemaps as array of strings.
* Use it You want to work with sitemap without saving it as files.
* @return array of strings
* @access public
*/
public function toArray() {
if ( isset( $this->sitemapIndex ) ) {
return array_merge( array( $this->sitemapIndex ), $this->sitemaps );
} else {
return $this->sitemaps;
}
}
/**
* Will print sitemaps.
* @access public
*/
public function outputSitemap( $template, $is_xml, $inner_sitemap = null ) {
add_filter( 'trp_stop_translating_page', '__return_true' );
ob_get_clean();
if ( $is_xml ) {
header( 'Content-Type: text/xml; charset=utf-8' );
} else {
ob_start();
}
if ( ! empty( $inner_sitemap ) && sgg_is_sitemap_index( $template ) && ! empty( $this->sitemaps[ $inner_sitemap ][0] ) ) {
echo $this->sitemaps[ $inner_sitemap ][0];
} else {
if ( ! empty( $this->sitemapIndex[1] ) ) {
$template = 'sitemap-index';
echo $this->sitemapIndex[1];
} else {
echo $this->sitemaps[0][1] ?? '';
}
}
if ( ! $is_xml ) {
$xml_source = ob_get_clean();
$xml = new \DOMDocument();
$xml->loadXML( $xml_source );
ob_start();
load_template(
GRIM_SG_PATH . '/templates/xsl/sitemap.php',
false,
compact( 'template', 'is_xml' )
);
$xsl_content = ob_get_clean();
$xsl = new \DOMDocument();
$xsl->loadXML( $xsl_content );
$proc = new \XSLTProcessor();
$proc->importStyleSheet( $xsl );
$dom_tran_obj = $proc->transformToDoc( $xml );
foreach ( $dom_tran_obj->childNodes as $node ) {
echo $dom_tran_obj->saveXML( $node ) . "\n";
}
}
if ( ob_get_contents() ) {
ob_end_flush();
}
}
}

View File

@@ -0,0 +1,920 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Google XML Sitemaps Generator\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-17 08:50+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: \n"
"Language: \n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Loco https://localise.biz/\n"
"X-Loco-Version: 2.6.6; wp-6.4.3\n"
"X-Domain: xml-sitemap-generator-for-google"
#: templates/partials/sidebar.php:102
msgid ""
" to take your Search Engine Optimization to the Next Level with unlocking "
"Premium Features."
msgstr ""
#. %s is Cached Time
#: includes/Cache.php:42
#, php-format
msgid "%s ago"
msgstr ""
#: templates/sections/general/additional.php:21
msgid "(Optional)"
msgstr ""
#. Sitemap Index URL
#: templates/xsl/sitemap.php:87
#, php-format
msgid "<a href=\"%s\">&#8592; Sitemap Index</a>"
msgstr ""
#: templates/partials/sidebar.php:116
msgid "Account & Premium Support"
msgstr ""
#: templates/sections/general/additional.php:57
msgid "Add New URL"
msgstr ""
#: templates/sections/general/general-settings.php:22
msgid "Add Sitemap Output URLs to site \"robots.txt\" file"
msgstr ""
#: templates/sections/general/additional.php:12
msgid "Additional URLs"
msgstr ""
#: templates/settings.php:23
msgid "Advanced"
msgstr ""
#: templates/sections/advanced/cache.php:105
msgid "Advanced Caching features to improve Sitemap data collection."
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:14
msgid ""
"All below options will be available after enabling Image Sitemap. Default "
"Sitemap will only include Images that are used in Content."
msgstr ""
#: templates/sections/advanced/cache.php:18
msgid ""
"All below options will be available after enabling Sitemap Cache. Sitemaps "
"Content will be cached for faster loading."
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:13
msgid ""
"All below options will be available after enabling Video Sitemap. Sitemap "
"will only include Videos that are used in Content."
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:58
msgid "Allow Image Types in your Image Sitemap."
msgstr ""
#: templates/fields/frequency.php:10
msgid "Always"
msgstr ""
#: templates/sections/general/posts-priority.php:56
msgid "Average Comments Count will be used for Priority Calculation"
msgstr ""
#: templates/sections/general/general-settings.php:13
msgid ""
"Basic Settings for your Sitemaps. Enabling all below options is recommended."
msgstr ""
#: templates/partials/sidebar.php:141
msgid "Bing Webmaster Tools"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:95
msgid "BMP"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:136
msgid "Broken Images"
msgstr ""
#: templates/sections/advanced/cache.php:15
msgid "Cache"
msgstr ""
#: templates/sections/advanced/cache.php:37
msgid "Cache Timeout:"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:99
msgid ""
"Caching YouTube API Data improves performance by storing and reusing "
"requested Video data from YouTube API."
msgstr ""
#: templates/partials/sidebar.php:85
msgid "can be displayed using Page Builder Widget or Shortcode"
msgstr ""
#: templates/sections/google-news/keywords.php:30
msgid "Categories"
msgstr ""
#: templates/sections/general/general-settings.php:63
msgid "Change API Key"
msgstr ""
#: includes/Dashboard.php:201
msgid "Changes saved!"
msgstr ""
#: templates/sections/general/general-settings.php:58
#: templates/sections/media-sitemaps/video-sitemap.php:86
msgid "Check API Key"
msgstr ""
#. %s Google Index Sitemap URL
#: templates/sections/general/sitemap-index.php:23
msgid "Choose Sitemap Structure:"
msgstr ""
#: templates/sections/advanced/cache.php:96
msgid "Clear Cache"
msgstr ""
#: templates/sections/advanced/cache.php:115
msgid "Clear cache when Page/Post created or updated"
msgstr ""
#: templates/partials/sidebar.php:29
msgid "Clear Sitemaps Cache"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:117
msgid "Clear YouTube Data Cache"
msgstr ""
#: templates/sections/general/posts-priority.php:55
msgid "Comments Average"
msgstr ""
#: templates/sections/general/posts-priority.php:40
msgid "Comments Count"
msgstr ""
#: templates/sections/general/sitemap-options.php:17
#: templates/sections/general/sitemap-options.php:46
#: templates/sections/media-sitemaps/content.php:18
#: templates/sections/media-sitemaps/content.php:38
#: templates/sections/google-news/content.php:18
#: templates/sections/google-news/content.php:50
msgid "Content"
msgstr ""
#: templates/sections/google-news/content.php:11
msgid "Content Options"
msgstr ""
#: templates/sections/google-news/keywords.php:38
msgid ""
"Custom Keywords Taxonomy will be available for Posts after enabling this "
"option."
msgstr ""
#: templates/sections/general/sitemap-options.php:42
#: templates/sections/media-sitemaps/content.php:30
#: templates/sections/google-news/content.php:42
msgid "Custom Post Types"
msgstr ""
#: templates/post-meta-box.php:15
msgid ""
"Custom Sitemap Options for the Current Post such as Exclude from Sitemap, "
"Post Priority, Post Frequency."
msgstr ""
#: templates/fields/frequency.php:16
msgid "Daily"
msgstr ""
#: templates/sections/advanced/cache.php:42
msgid "day(s)"
msgstr ""
#: includes/Notices.php:63 includes/Notices.php:85
msgid "Dismiss"
msgstr ""
#: templates/sections/general/posts-priority.php:25
msgid "Do not use Priority Calculation"
msgstr ""
#: templates/partials/sidebar.php:120
msgid "Documentation"
msgstr ""
#: templates/sections/advanced/import-export.php:28
msgid "Download Settings Data File"
msgstr ""
#: templates/partials/sidebar.php:88
msgid "Elementor"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:108
msgid "Enable Cache for YouTube Data"
msgstr ""
#: templates/sections/google-news/general-settings.php:22
msgid "Enable Google News"
msgstr ""
#: templates/sections/general/html-sitemap.php:29
msgid "Enable HTML Sitemap"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:24
msgid "Enable Image Sitemap"
msgstr ""
#: templates/sections/general/general-settings.php:34
msgid "Enable IndexNow Protocol (Microsoft Bing, Seznam.cz, Naver, Yandex)"
msgstr ""
#: templates/sections/advanced/cache.php:28
msgid "Enable Sitemap Cache"
msgstr ""
#: templates/sections/google-news/stock-tickers.php:24
msgid "Enable Stock Tickers "
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:22
msgid "Enable Video Sitemap"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:166
msgid ""
"Enabling this option includes Featured Images from Pages, Posts, and Custom "
"Posts to your Image Sitemap."
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:192
msgid ""
"Enabling this option includes WooCommerce Gallery Images from Products to "
"your Image Sitemap."
msgstr ""
#: templates/sections/general/additional.php:18
msgid ""
"Enter the URL to the External Page. For example: https://example.com/blog or "
"www.example.com/account."
msgstr ""
#: templates/fields/post-row.php:13 templates/fields/content.php:11
#: templates/sections/general/exclude.php:12
#: templates/sections/google-news/exclude.php:12
msgid "Exclude"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:151
msgid "Exclude Broken Images"
msgstr ""
#: templates/sections/general/exclude.php:35
#: templates/sections/google-news/exclude.php:36
msgid "Exclude Categories and Tags:"
msgstr ""
#: templates/sections/general/exclude.php:23
msgid "Exclude Pages/Posts:"
msgstr ""
#: templates/sections/google-news/exclude.php:23
msgid "Exclude Posts:"
msgstr ""
#: templates/sections/advanced/import-export.php:22
msgid "Export Settings"
msgstr ""
#: templates/sections/general/additional.php:15
msgid "External URLs which should be included in your Sitemap:"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:161
msgid "Featured Images"
msgstr ""
#: templates/partials/sidebar.php:25
msgid "Flush Rewrite Rules"
msgstr ""
#: templates/settings.php:20
msgid "General"
msgstr ""
#: templates/sections/general/general-settings.php:11
#: templates/sections/google-news/general-settings.php:11
msgid "General Settings"
msgstr ""
#: templates/partials/pro-overlay.php:9
msgid "Get Now"
msgstr ""
#: includes/Dashboard.php:348
msgid "Get Pro"
msgstr ""
#: templates/partials/sidebar.php:101
msgid "Get Pro Version now"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:108
msgid "GIF"
msgstr ""
#: includes/Sitemap.php:129 templates/settings.php:21
#: templates/partials/sidebar.php:56 templates/sections/advanced/cache.php:67
msgid "Google News"
msgstr ""
#: templates/sections/google-news/output.php:35
msgid "Google News for other languages:"
msgstr ""
#: templates/partials/sidebar.php:132
msgid "Google News Help Center"
msgstr ""
#: templates/sections/google-news/output.php:13
msgid "Google News URL"
msgstr ""
#: templates/sections/google-news/output.php:23
msgid "Google News URL:"
msgstr ""
#: templates/partials/sidebar.php:129
msgid "Google Search Console"
msgstr ""
#. Name of the plugin
msgid "Google XML Sitemaps Generator"
msgstr ""
#: includes/Dashboard.php:26 templates/settings.php:11
msgid "Google XML Sitemaps Generator Settings"
msgstr ""
#. Description of the plugin
msgid ""
"Greatly improves SEO by generating XML Sitemaps, HTML Sitemaps and Google "
"News, helping search engines like Google, Bing, Yahoo and others index your "
"site more effectively."
msgstr ""
#: templates/partials/sidebar.php:90
msgid "Gutenberg"
msgstr ""
#: templates/sections/advanced/import-export.php:24
msgid ""
"Here you can download your current Settings. Keep this safe as you can use "
"it as a backup if anything goes wrong."
msgstr ""
#: templates/sections/general/html-sitemap.php:20
msgid "Here you can enable HTML Sitemap, customize Output URL and preview."
msgstr ""
#: templates/sections/google-news/output.php:15
msgid "Here you can preview your Google News and customize Output URL."
msgstr ""
#: templates/sections/general/xml-sitemap.php:15
msgid "Here you can preview your XML Sitemap and customize Output URL."
msgstr ""
#: templates/sections/advanced/cache.php:41
msgid "hour(s)"
msgstr ""
#: templates/fields/frequency.php:13
msgid "Hourly"
msgstr ""
#: templates/partials/sidebar.php:48 templates/partials/sidebar.php:84
#: templates/sections/advanced/cache.php:59
#: templates/sections/general/html-sitemap.php:14
msgid "HTML Sitemap"
msgstr ""
#: templates/sections/general/html-sitemap.php:44
msgid "HTML Sitemap URL:"
msgstr ""
#: templates/sections/general/html-sitemap.php:56
msgid "HTML Sitemaps for other languages:"
msgstr ""
#. URI of the plugin
msgid "https://wordpress.org/plugins/xml-sitemap-generator-for-google/"
msgstr ""
#. Author URI of the plugin
msgid "https://wpgrim.com/"
msgstr ""
#: templates/sections/media-sitemaps/content.php:11
msgid "Image & Video Content Options"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:53
msgid "Image MIME Types"
msgstr ""
#: includes/Sitemap.php:132 templates/partials/sidebar.php:64
#: templates/sections/advanced/cache.php:75
#: templates/sections/media-sitemaps/image-sitemap.php:11
msgid "Image Sitemap"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:39
msgid "Image Sitemap URL:"
msgstr ""
#: templates/sections/advanced/import-export.php:7
#: templates/sections/advanced/import-export.php:14
msgid "Import Settings"
msgstr ""
#: templates/fields/post-row.php:12 templates/fields/content.php:10
#: templates/sections/general/sitemap-options.php:18
#: templates/sections/general/sitemap-options.php:47
#: templates/sections/media-sitemaps/content.php:19
#: templates/sections/media-sitemaps/content.php:39
#: templates/sections/google-news/content.php:19
#: templates/sections/google-news/content.php:51
msgid "Include"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:176
msgid "Include Featured Images"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:202
msgid "Include WooCommerce Gallery Images"
msgstr ""
#: includes/Dashboard.php:60
msgid "IndexNow API Key changed successfully."
msgstr ""
#. %s: IndexNow API Key
#: templates/sections/general/general-settings.php:49
#, php-format
msgid "INDEXNOW API KEY: %s"
msgstr ""
#: templates/partials/sidebar.php:138
msgid "IndexNow Protocol"
msgstr ""
#: templates/sections/general/general-settings.php:41
msgid ""
"IndexNow Protocol informs search engines like Microsoft Bing, Seznam.cz, "
"Naver, and Yandex about all updates of your website, including changes when "
"saving Posts."
msgstr ""
#: includes/Notices.php:18
msgid "Invalid nonce."
msgstr ""
#: includes/ImportExport.php:37
msgid "Invalid settings file or data."
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:69
msgid "JPEG"
msgstr ""
#: templates/sections/google-news/keywords.php:12
msgid "Keywords"
msgstr ""
#: templates/sections/google-news/keywords.php:24
msgid "Keywords from:"
msgstr ""
#: templates/sections/google-news/keywords.php:31
msgid "Keywords Taxonomy"
msgstr ""
#: templates/sections/advanced/cache.php:46
msgid "Last Cached Time:"
msgstr ""
#: templates/sections/general/additional.php:30
msgid "Last Modified"
msgstr ""
#: templates/sections/general/additional.php:20
msgid "Last Modified:"
msgstr ""
#: templates/partials/sidebar.php:111
msgid "Links"
msgstr ""
#: templates/settings.php:22
msgid "Media Sitemaps"
msgstr ""
#: templates/sections/advanced/optimize.php:29
msgid "Minimize Sitemap source code"
msgstr ""
#: templates/sections/advanced/cache.php:40
msgid "minute(s)"
msgstr ""
#: templates/fields/frequency.php:22
msgid "Monthly"
msgstr ""
#: templates/fields/frequency.php:28
msgid "Never"
msgstr ""
#: includes/Cache.php:43
msgid "No Cache"
msgstr ""
#: templates/sections/general/additional.php:37
msgid "No URLs added yet!"
msgstr ""
#: templates/fields/select.php:9
msgid "None"
msgstr ""
#: templates/sections/advanced/cache.php:91
msgid ""
"Note: Sitemap Cache will only be created when someone opens/visits the "
"Sitemap on front-end."
msgstr ""
#: templates/sections/general/posts-priority.php:41
msgid "Number of Post Comments will be used for Priority Calculation"
msgstr ""
#: templates/sections/google-news/stock-tickers.php:33
msgid ""
"Once this option is enabled, you will be able to specify values under the "
"custom Stock Tickers Taxonomy."
msgstr ""
#: templates/sections/advanced/optimize.php:13
msgid "Optimize"
msgstr ""
#: templates/partials/sidebar.php:21
msgid "Ping IndexNow Protocol"
msgstr ""
#: templates/sections/general/posts-priority.php:18
msgid "Please choose a priority for calculating each of posts:"
msgstr ""
#: templates/sections/general/exclude.php:17
msgid ""
"Please search and choose here Pages, Posts, Custom Posts, Categories and "
"Tags that should be excluded from Sitemap:"
msgstr ""
#: templates/sections/google-news/exclude.php:17
msgid ""
"Please search and choose here Posts that should be excluded from Google News:"
msgstr ""
#: templates/sections/google-news/keywords.php:17
msgid ""
"Please select the source from which the Google News Keywords should be "
"extracted."
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:82
msgid "PNG"
msgstr ""
#: templates/sections/general/posts-priority.php:12
msgid "Posts Priority"
msgstr ""
#: templates/sections/general/posts-priority.php:26
msgid ""
"Posts will have the same priority which is defined in \"Sitemap Options\""
msgstr ""
#: templates/partials/sidebar.php:37
msgid "Preview"
msgstr ""
#: templates/sections/google-news/output.php:34
msgid "Preview your Google News:"
msgstr ""
#: templates/sections/general/html-sitemap.php:55
msgid "Preview your HTML Sitemap:"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:46
msgid "Preview your Image Sitemap:"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:44
msgid "Preview your Video Sitemap:"
msgstr ""
#: templates/sections/general/xml-sitemap.php:34
msgid "Preview your XML Sitemap:"
msgstr ""
#: templates/sections/general/additional.php:28
#: templates/sections/general/sitemap-options.php:19
#: templates/sections/general/sitemap-options.php:48
msgid "Priority"
msgstr ""
#: includes/Dashboard.php:340
msgid "Pro Version"
msgstr ""
#: includes/Notices.php:80
msgid "Pro version"
msgstr ""
#: templates/sections/google-news/general-settings.php:37
msgid "Publication Name:"
msgstr ""
#: includes/Dashboard.php:366 templates/partials/sidebar.php:126
msgid "Rate ★★★★★"
msgstr ""
#: templates/partials/sidebar.php:103
msgid "Read More"
msgstr ""
#: templates/sections/advanced/import-export.php:16
msgid "Select the JSON file in order to Import Settings."
msgstr ""
#: includes/Dashboard.php:330
msgid "Settings"
msgstr ""
#: includes/ImportExport.php:27
msgid "Settings imported successfully."
msgstr ""
#: templates/partials/sidebar.php:135
msgid "Show up in Google News"
msgstr ""
#: templates/sections/general/sitemap-index.php:29
msgid "Single Sitemap"
msgstr ""
#: includes/Sitemap.php:125 includes/Sitemap.php:138
msgid "Sitemap"
msgstr ""
#: includes/Sitemap.php:141 templates/sections/general/sitemap-index.php:36
msgid "Sitemap Index"
msgstr ""
#: templates/sections/general/sitemap-options.php:11
msgid "Sitemap Options"
msgstr ""
#: templates/sections/advanced/optimize.php:20
msgid "Sitemap source code will be compressed into a single line."
msgstr ""
#: templates/sections/general/sitemap-index.php:11
msgid "Sitemap Structure"
msgstr ""
#: includes/Dashboard.php:74 includes/Tools.php:43
msgid "Sitemaps Cache cleared."
msgstr ""
#: templates/sections/general/xml-sitemap.php:35
msgid "Sitemaps for other languages:"
msgstr ""
#: templates/sections/advanced/cache.php:100
msgid "Smart Caching"
msgstr ""
#. %s General Settings URL
#: templates/sections/google-news/general-settings.php:49
msgid "Source Labels:"
msgstr ""
#: templates/sections/google-news/stock-tickers.php:12
msgid "Stock Tickers"
msgstr ""
#: templates/sections/google-news/stock-tickers.php:31
msgid "Stock tickers are most commonly used in articles related to business."
msgstr ""
#: includes/Dashboard.php:365
msgid "Support"
msgstr ""
#: templates/partials/sidebar.php:123
msgid "Support Forum"
msgstr ""
#: templates/sections/google-news/keywords.php:29
msgid "Tags"
msgstr ""
#: templates/partials/pro-overlay.php:8
msgid "This feature is available on Premium version"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:56
msgid ""
"This is required field for retrieving the data from Youtube embeds if you "
"are using them in Contents."
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:141
msgid ""
"This option allows to exclude Broken or Not Existing 404 images. Recommended "
"to use this option with Sitemap Cache, as it affects to Sitemap Generating "
"Speed."
msgstr ""
#: templates/sections/general/sitemap-options.php:13
msgid "This Options will be used for generating your Sitemap."
msgstr ""
#: templates/sections/media-sitemaps/content.php:13
msgid "This settings will be used for generating Image & Video Sitemaps."
msgstr ""
#: templates/sections/google-news/content.php:13
msgid "This settings will be used for generating your Google News."
msgstr ""
#: templates/partials/sidebar.php:81
msgid "Tips"
msgstr ""
#: templates/partials/sidebar.php:15
msgid "Tools"
msgstr ""
#: templates/fields/autocomplete.php:11
msgid "Type to Search..."
msgstr ""
#: templates/sections/general/additional.php:29
#: templates/sections/general/sitemap-options.php:20
#: templates/sections/general/sitemap-options.php:49
msgid "Update Frequency"
msgstr ""
#: templates/sections/general/additional.php:27
msgid "URL to External Page"
msgstr ""
#: templates/sections/general/additional.php:17
msgid "URL to External Page:"
msgstr ""
#: includes/Sitemap.php:135 templates/partials/sidebar.php:72
#: templates/sections/advanced/cache.php:83
#: templates/sections/media-sitemaps/video-sitemap.php:11
msgid "Video Sitemap"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:37
msgid "Video Sitemap URL:"
msgstr ""
#: templates/sections/advanced/import-export.php:9
msgid ""
"WARNING! This will overwrite all existing Settings, please proceed with "
"caution or backup current Settings!"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:121
msgid "WEBP"
msgstr ""
#: templates/fields/frequency.php:19
msgid "Weekly"
msgstr ""
#: templates/sections/general/sitemap-index.php:30
msgid "will be generated with all links"
msgstr ""
#: templates/sections/general/sitemap-index.php:37
msgid "will be generated with Inner Sitemaps"
msgstr ""
#: templates/sections/media-sitemaps/image-sitemap.php:187
msgid "WooCommerce Gallery"
msgstr ""
#: includes/Tools.php:39
msgid "WordPress Rewrite Rules flushed."
msgstr ""
#: templates/partials/sidebar.php:92
msgid "WPBakery (Visual Composer)"
msgstr ""
#. Author of the plugin
msgid "WPGrim"
msgstr ""
#: templates/partials/sidebar.php:41 templates/sections/advanced/cache.php:52
#: templates/sections/general/xml-sitemap.php:13
msgid "XML Sitemap"
msgstr ""
#: templates/sections/general/xml-sitemap.php:24
msgid "XML Sitemap URL:"
msgstr ""
#: templates/partials/sidebar.php:147
msgid "XML Sitemap Validator"
msgstr ""
#: includes/Dashboard.php:27
msgid "XML Sitemaps"
msgstr ""
#: templates/partials/sidebar.php:144
msgid "Yandex Webmaster"
msgstr ""
#: templates/fields/frequency.php:25
msgid "Yearly"
msgstr ""
#: includes/Notices.php:65
msgid "Yes, Rate Now"
msgstr ""
#: includes/Notices.php:87
msgid "Yes, Read More"
msgstr ""
#: templates/sections/general/additional.php:22
msgid ""
"You can select the Last Modified datetime for the URL or leave it empty "
"(default) to always show the Current Datetime on Sitemap."
msgstr ""
#: includes/Dashboard.php:110
msgid "YouTube API key passed the check successfully."
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:51
msgid "YouTube Data API"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:64
msgid "YouTube Data API v3 Key:"
msgstr ""
#: templates/sections/media-sitemaps/video-sitemap.php:93
msgid "YouTube Data Cache"
msgstr ""
#: includes/Dashboard.php:95
msgid "YouTube Data Cache cleared."
msgstr ""

View File

@@ -0,0 +1,806 @@
=== Dynamic XML Sitemaps Generator for Google ===
Contributors: wpgrim
Donate link: https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=donate&utm_campaign=xml_sitemap
Tags: sitemap, xml sitemap, google news, image sitemap, video sitemap, google sitemaps, xml, google, seo, sitemaps, site map, robots, google, sitemap generator, dynamic sitemap, generator, google webmaster tools, add pages to sitemap, add posts to sitemap, wordpress sitemap plugin, sitemap for search engines, indexing sitemap, custom sitemap, multilingual sitemap, news sitemap, seo friendly sitemap, woocommerce sitemap, image sitemap generator
Requires at least: 5.0
Requires PHP: 5.6
Tested up to: 6.9.1
Stable tag: 2.2.9
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Boost SEO 🚀 with powerful XML, HTML, Image, Video & Google News sitemaps for better search engine indexing.
== Description ==
## XML Sitemaps
Google XML Sitemaps Generator is a WordPress Sitemap plugin that improves your website's SEO by creating special XML Sitemaps for Search Engines like Google, Yahoo, Bing, Ask.com, and Yandex to index your site faster.
This plugin generates detailed **XML Sitemaps** that include your website's Pages, Posts, Custom Posts, and Taxonomies, enhancing your website's Search Engine Optimization (SEO) score. Plugin offers following Sitemaps:
* **General Sitemap** single XML Sitemap with all important links
* **Google News Sitemap** optimized for fast news indexing and higher visibility
* **Sitemap Index** organize multiple sitemaps in one index for better structure
* **Image Sitemap** improve indexing of images, galleries, and media content
* **Video Sitemap** help Google discover and rank your video content faster
* **Multilingual Sitemap** fully compatible with WPML, Polylang, and TranslatePress
* **WooCommerce Support** includes products, categories, and tags in sitemaps
* **Customizable Control** exclude specific posts, pages, or taxonomies; add custom URLs; set priority and frequency rules
* **SEO-Friendly & Performance Optimized** built-in caching system, robots.txt integration, WP-CLI commands, and seamless compatibility with popular SEO plugins (Yoast, Rank Math, The SEO Framework)
⭐ [Dynamic XML Sitemaps Generator for Google PRO](https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=documentation&utm_campaign=xml_sitemap)
⭐ [Documentation](https://wpgrim.com/docs/google-xml-sitemaps-generator/general/settings/?utm_source=wordpressorg&utm_medium=documentation&utm_campaign=xml_sitemap)
## Sitemap Structure
The plugin offers two primary XML Sitemap structures: **Single Sitemap** and **Sitemap Index**. The Single Sitemap displays all your website's content in a single XML Sitemap, while the Sitemap Index shows multiple XML Sitemaps in a single Sitemap Index.
**Sitemap Index** feature enables you to manage your sitemaps with **Multiple Inner Sitemaps** for various content types such as Pages, Posts, Custom Posts, Images, Videos and more. This feature makes easy the management of your Sitemaps and keep them organized.
## Google News
Make your website's News easily discoverable by Search Engines with Google News feature. By enabling "Google News" in the settings, a dynamic [Google News Sitemap](https://developers.google.com/search/docs/crawling-indexing/sitemaps/news-sitemap) will be created automatically. Google News Sitemap is fully compatible with popular multilingual plugins like **WPML**, **Polylang**, and **TranslatePress**.
The Google News Sitemap includes all the required fields such as **Publication Name**, **Language**, **Title**, and **Publication Date**. Additionally, it is fully compatible with the Google Publisher Center sitemap protocol, ensuring that your website's content is properly indexed and displayed in Google News.
## Image Sitemap
The Dynamic Image Sitemap is a valuable tool for optimizing website indexing and search engine visibility. By including images from Pages, Posts, and Custom Posts Content, it offers a comprehensive representation of visual content on your site. Additionally, its adherence to the [Google Image Sitemaps](https://developers.google.com/search/docs/crawling-indexing/sitemaps/image-sitemaps) structure ensures compatibility and optimal performance within the search engine ecosystem.
## Video Sitemap
Video Sitemap will also be dynamically generated using collected Videos from Pages, Posts, and Custom Posts Content that contains Playlist Shortcode or <video> tag nd fully compatible with [Google Video Sitemaps](https://developers.google.com/search/docs/crawling-indexing/sitemaps/video-sitemaps) structure. Title, Thumbnail, Description, and Duration fields will be respectively generated from Video Attachment's Title, Featured Image, Caption, and Length.
## Custom Sitemap URLs
Customizing your XML Sitemap is ease with Custom Sitemap URLs feature. You can add **External or Internal URLs** to your XML Sitemap under the Plugin Settings, making it easy to customize your XML Sitemap to fit your specific needs. Also, you can add **Custom Sitemaps** to the Sitemap Index, if you have Static or Additional Sitemaps.
In addition, Google XML Sitemaps Generator plugin allows you to display a Sitemap under a **Custom URL** on your website, providing an additional level of customization.
## Sitemap Options
This plugin provides you with a very simple and clean UI to set **Priority**, **Frequency** options and easily **Include/Exclude** Pages, Posts, Custom Posts, Archives, Authors, Categories, Taxonomies and Tags into your Sitemap.
## Cache
The WordPress XML Sitemap plugin comes equipped with a Cache feature that automatically caches Sitemap Data when a user visits the Sitemap page. This means that subsequent visits to the sitemap page will be faster as the cached data is quickly retrieved instead of generating the Sitemap from scratch.
Cache feature also includes options to set a **Caching Timeout**, view the **Last Cached Time**, and **Clear Cache** when necessary. These features help to improve the performance of your website and ensure that your Sitemap is always up-to-date for Search Engines to crawl.
Here is a short list of Google XML Sitemap plugin features.
**Features:**
* Multiple Sitemaps by Sitemap Index 🔥
* Custom XML Sitemap URL 🔥
* IndexNow Protocol for indexing Microsoft Bing, Seznam.cz, Naver, and Yandex
* Control Sitemap Options for all Pages, Posts, Custom Posts, Archives, Authors, Categories, Taxonomies and Tags 🔥
* Include/Exclude Taxonomies, Categories, Tags 🔥
* Add Custom Sitemaps to Sitemap Index
* Add Custom External/Internal URLs to your XML Sitemap 🔥
* Automatically add Sitemaps to robots.txt
* Links Per Page for Sitemap Index 🔥
* Static Sitemap File detector
* Toolbar with most helpful Actions & Links
* Disables auto-generated WP Sitemaps
* Setup Wizard 🔥
* WP-CLI commands for Sitemap generation **[NEW]** 🔥
* Multisite Network compatible
* WooCommerce compatible
* Multilingual Sitemap 🔥
* WPML compatible
* Polylang compatible
* TranslatePress compatible
* FooGallery compatible
* Yoast SEO compatible with noindex
* Rank Math SEO compatible with noindex
* SEO Framework compatible
* User-Friendly Interface
* No Coding required
**Google News Features:**
* Sitemap Tags: Publication Name, Language, Title and Publication Date
* Custom Google News URL 🔥
* Custom News Publication Name
* WPML compatible
* Polylang compatible
* TranslatePress compatible
**Image Sitemap Features**
* Hide Image Previews **[NEW]**
* Multiple Sitemaps by Sitemap Index
* Include Pages & Posts
* Custom Image Sitemaps URLs
**Video Sitemap Features**
* Multiple Sitemaps by Sitemap Index
* Include Pages & Posts
* Custom Video Sitemaps URLs
**Advanced Features**
* Cache Sitemaps 🔥
* Cache Expiration Time
* Last Cached Time of Sitemaps
* Import & Export Settings
## 🌟 Upgrade to Pro Version
Upgrade to the [Google XML Sitemaps Generator Pro](https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=content&utm_campaign=xml_sitemap) to get access to even more features, like an HTML Sitemap, Exclusion of specific Pages and Custom Posts from your Sitemap, Google News Premium Features, and more.
[Get Pro Version now](https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=get-pro-version&utm_campaign=xml_sitemap) and take your Search Engine Optimization to the Next Level.
**Custom Priority and Frequency for a Single Page/Post**
Customize the **Priority**, **Frequency**, and **Exclude from Sitemap** options for a Single Post, Page, or CPT [with the Pro Version](https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=post-meta&utm_campaign=xml_sitemap).
**HTML Sitemap**
Improve your website's navigation with HTML Sitemap feature. This feature allows you to create an HTML Sitemap that can be displayed on your website's pages using popular Page Builder Widgets such as Elementor, Gutenberg, WPBakery, or simple Shortcode.
You can also customize your HTML Sitemap by choosing which Post Types to display, including Pages, Posts, and Custom Post Types, through the convenient multiselect option. With this feature, you can easily enhance your website's user experience and make it more SEO-friendly. [Try Pro Version](https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=html-sitemap&utm_campaign=xml_sitemap) today!
**Premium Features**
* Exclude Pages, Posts, Custom Posts from Sitemap
* Exclude Categories and Tags from Sitemap 🔥
* Include only selected Categories & Tags **[NEW]**
* HTML Sitemap 🔥
* Single Post/Page Custom Sitemap Options: 🔥
-- Exclude from Sitemap
-- Post Priority
-- Post Frequency
* Posts Priority Automatic Calculation:
-- by Number of Comments
-- by Average Comments Count
* Page Builder Widgets and Shortcode for **HTML Sitemap**:
-- Elementor widget
-- Gutenberg block
-- WPBakery (Visual Composer) widget
-- **[html-sitemap post-types="page,post,.." ..]**
* Sitemap Custom Colors **[NEW]** 🔥
* No Branding Marks 🔥
* Premium Support
**Google News Premium Features**
* Include Custom Post Types
* Include Taxonomies
* Keywords 🔥
* Stock Tickers 🔥
* Exclude Posts and Custom Posts
* Exclude Categories and Tags 🔥
* Include only selected Categories & Tags **[NEW]**
**Image Sitemap Premium Features**
* Image Sitemap MIME Types
* Exclude Broken (404) Images 🔥
* Include Featured Images
* Include WooCommerce Gallery 🔥
* Include Custom Post Types
**Video Sitemap Premium Features**
* YouTube videos 🔥
* Vimeo videos **[NEW]** 🔥
* X (Twitter) videos **[NEW]** 🔥
* Include Custom Post Types
**Advanced Premium Features**
* Smart Caching 🔥
* Minimize Sitemap source code
* Cron Job **[NEW]** 🔥
⭐ [Get PRO Version Now](https://wpgrim.com/google-xml-sitemaps-generator-pro/?utm_source=wordpressorg&utm_medium=get_pro&utm_campaign=xml_sitemap)
## More Powerful Plugins
[Classic Editor and Classic Widgets](https://wordpress.org/plugins/classic-editor-and-classic-widgets/)
Developed with ❤️ by [WP Grim](https://wpgrim.com/?utm_source=wordpressorg&utm_medium=direct&utm_campaign=xml_sitemap)
== Screenshots ==
1. General Settings
2. Sitemap Structure
3. Sitemap Options
4. Google News Settings
5. Image Sitemap Settings
6. Video Sitemap Settings
7. Advanced Settings
8. WP CLI & Import/Export Tools
9. XML Sitemap
10. Sitemap Index
11. Video Sitemap
12. Image Sitemap
13. Google News
14. Multilingual Sitemap
15. Setup Wizard
== Frequently Asked Questions ==
= Where can I find Plugin Settings? =
You can find plugin options under **Settings > XML Sitemaps**.
= How to fix Sitemap 404 Not Found error? =
First, try to flush Rewrite Rules. You can find **Flush Rewrite Rules** button under **Settings > XML Sitemaps > Tools** sidebar.
If you are using NGINX webserver, you may need to add extra Rewrite Rules to your NGINX configuration file. You can find the NGINX configuration in the **Webserver Configuration** section under **Settings > XML Sitemaps**.
= How to submit Sitemap URL to Google Webmaster Tools? =
1. Sign in to Google [Search Console](https://search.google.com/search-console).
2. Select your website in the Sidebar and click on **Sitemaps** menu.
3. Enter **https://yoursite.com/sitemap.xml** in "Add a new sitemap" field and click **Submit**.
= Can I modify Priority and Frequency options? =
You can find Sitemap Content Options under **Settings > XML Sitemaps > XML Sitemap**.
= How to publish Posts on Google News? =
Follow this guide in order to [Show up your Publications on Google News](https://support.google.com/news/publisher-center/answer/9607025?hl=en). Also, you need to [Create a Google News section](https://support.google.com/news/publisher-center/answer/9548609?hl=en) from part of your website.
You need also to add the Sitemap URL to your [Google Search Console](https://search.google.com/search-console) account for validation.
= How to show HTML Sitemap on my Pages? =
You can show HTML Sitemap on your Pages using popular Page Builder Widgets such as **Elementor**, **Gutenberg**, **WPBakery (Visual Composer)**, or simple Shortcode like:
**[html-sitemap post-types="page,post,.." show-featured-image="true" show-date="true" date-format="F j, Y"]**
= How to set custom Priority and Frequency for chosen Page, Post, or Term? =
You can set custom Priority and Frequency for chosen Page, Post, or Term using filters:
**sitemap_post_priority**, **sitemap_post_frequency**, **sitemap_term_priority**, **sitemap_term_frequency**
Example:
``
add_filter( 'sitemap_post_priority', 'my_sitemap_post_priority', 10, 2 );
function my_sitemap_post_priority( $priority, $post_id ) {
if ( $post_id === 1 ) {
$priority = 9; // priority from 0 to 10
}
return $priority;
}
``
= How to generate Sitemap using CLI? =
You can generate Sitemap using CLI command:
`wp sitemap generate`
You can generate a specific Sitemap type:
`wp sitemap generate --template=image-sitemap`
Allowed Sitemap types are **sitemap**, **image-sitemap**, **video-sitemap**, and **google-news**. Default template is **sitemap**.
== Installation ==
This section describes how to install the plugin and get it working.
1. Upload the plugin files to the `/wp-content/plugins/` directory, or install the plugin through the WordPress plugins screen directly.
2. Activate the plugin through the **Plugins** menu in WordPress
3. Please find more details on [Plugin Documentation](https://wpgrim.com/docs/google-xml-sitemaps-generator/general/settings/?utm_source=wordpressorg&utm_medium=installation&utm_campaign=xml_sitemap)
4. Set Up Page in **Settings -> XML Sitemaps**.
== Changelog ==
= 2.2.9 - 2026-03-05 =
* Saving autoload options removed for better performance
= 2.2.8 - 2026-02-12 =
* WordPress 6.9.1 compatible
* Pro Version: Check YouTube & Vimeo API keys issue fixed
= 2.2.7 - 2026-02-06 =
* Additional URLs appearance improved
* Saving Custom Sitemap Options on Media page issue fixed
* Media Post Custom Sitemap Priority and Frequency options implemented
= 2.2.6 - 2026-01-25 =
* Media Pages added to main XML Sitemap
= 2.2.5 - 2026-01-08 =
* Image Sitemap: Disable XSL Stylesheet option added
* Video Sitemap: Disable XSL Stylesheet option added
* Admin notices are hidden on Settings pages
= 2.2.4 - 2025-12-25 =
* Dashboard UI/UX improved
= 2.2.3 - 2025-12-03 =
* WordPress 6.9 compatible
* Wizard design updated
= 2.2.2 - 2025-11-22 =
* Multilingual Sitemap: Sitemap URLs trailing slash issue fixed. Thanks to @sunlight1976
= 2.2.1 - 2025-11-07 =
* Top Navigation UI/UX improved
* Admin Settings page UI/UX improved
* WordPress 6.8.3 compatible
* Minor bug fixes
= 2.2.0 - 2025-10-20 =
* New Admin Panel Design
* Multilingual Sitemap: Home page URL trailing slash issue fixed
= 2.1.17 - 2025-10-08 =
* Multilingual Sitemap: Default language issue fixed
= 2.1.16 - 2025-09-28 =
* UI/UX improvements
= 2.1.15 - 2025-09-10 =
* Spanish, French, Portuguese, Polish translations added
= 2.1.13 - 2025-08-29 =
* Minor bug fixes
= 2.1.12 - 2025-08-12 =
* WordPress 6.8.2 compatible
= 2.1.11 - 2025-07-05 =
* Troubleshoot section added to Settings page
* WP CLI instructions section added to Settings page
* Pro Version: Cron Job feature added
* **sgg_sitemap_exclude_post_ids** and **sgg_sitemap_exclude_term_ids** filters added for customizing Exclude Post and Term IDs
* **sgg_sitemap_include_only_term_ids** filter added for customizing Include only Term IDs
= 2.1.10 - 2025-06-17 =
* Media Sitemap: BeeTheme compatibility added, as it uses post_meta for storing content
* Media Sitemap: Post Parent URL issue fixed
* Media Sitemap: Noindex Posts excluded from Image & Video Sitemaps
= 2.1.9 - 2025-05-22 =
* Sitemap Generator CLI command added
* **template_redirect** action replaced with **parse_request** action for early execution of Sitemaps
= 2.1.8 - 2025-05-18 =
* Old media_sitemap Content checks removed
= 2.1.7 - 2025-05-16 =
* Creation of dynamic property is deprecated PHP error fixed. Thanks to @track77 and @btreece84
= 2.1.5 - 2025-05-15 =
* SEO Framework noindex Pages, Posts, and Custom Posts excluded from Sitemap
* SEO Framework noindex Categories and Taxonomies excluded from Sitemap
* Image Sitemap: AVIF image support added
* Google News: SEO Framework custom title support added
* Image Sitemap & Video Sitemap settings separatedy
* WordPress 6.8.1 compatible
= 2.1.4 - 2025-04-24 =
* Google News: **xml_sitemap_google_news_title** filter added for customizing Title
* Child Posts URL issue fixed
= 2.1.3 - 2025-04-15 =
* WordPress 6.8 compatible
= 2.1.2 - 2025-03-18 =
* Caching Chunk Size increased
= 2.1.1 - 2025-03-18 =
* Minor bug fixes
= 2.1.0 - 2025-03-14 =
* Image Sitemap: Multiple Sitemaps (Per Paged) by Sitemap Index feature added
* Image Sitemap: Hide Image Previews feature added
* Video Sitemap: Multiple Sitemaps (Per Paged) by Sitemap Index feature added
* Media Sitemaps: Database Queries optimized
* Media Sitemaps: Smart Caching feature implemented for faster loading
* **xml_sitemap_disable_post_meta_fields** filter added for disabling Post Meta Fields
* **xml_sitemap_disable_post_meta__exclude_sitemap**, **xml_sitemap_disable_post_meta__priority**, **xml_sitemap_disable_post_meta__frequency** filters added for disabling Post Meta Fields
= 2.0.8 - 2025-03-02 =
* Pro Version: XML Sitemaps > Include only selected Categories & Tags feature added
* Pro Version: Google News > Include only selected Categories & Tags feature added
= 2.0.7 - 2025-02-23 =
* Pro Version: Video Sitemap > X (Twitter) video support added
* WordPress 6.7.2 compatible
= 2.0.6 - 2025-02-10 =
* **sgg_sitemap_colors** filter added for customizing Sitemap Colors
* Pro Version: Sitemap Colors feature added with Color Pickers
* Pro Version: Toggle Branding Marks feature added
= 2.0.5 - 2025-01-07 =
* Additional URLs: Add Bulk URLs feature added
= 2.0.4 - 2024-12-07 =
* get_category_link() replaced with get_term_link() for Taxonomy URLs
* Compatibility with Custom Permalinks plugins improved
= 2.0.3 - 2024-11-22 =
* Archive Sitemap wp_ table prefix issue fixed. Thanks to @jdorner
* **xml_sitemaps_site_url** filter added for customizing Site URL
* WordPress 6.7.1 compatible
= 2.0.2 - 2024-11-13 =
* WordPress 6.7 compatible
= 2.0.1 - 2024-11-04 =
* Sitemap Index: Showing Single Sitemap issue fixed. Thanks to @waldub
* Image Sitemap: Duplicating Image Sizes removed
= 2.0.0 - 2024-10-14 =
* Setup Wizard added
= 1.9.12 - 2024-09-26 =
* Multiple Sitemap queries improved
= 1.9.11 - 2024-09-25 =
* WPML Category Sitemap issue fixed. Thanks to @waldub
* WPML compatibility improved
= 1.9.10 - 2024-09-12 =
* WordPress 6.6.2 compatible
* Media Sitemap: Outputting shortcodes issue fixed
= 1.9.9 - 2024-09-03 =
* Pro Version: Video Sitemap > Vimeo video support added
* WPML language names as parameter issue fixed
= 1.9.8 - 2024-07-29 =
* WordPress 6.6.1 compatible
* Exclude Categories and Tags query optimized
= 1.9.7 - 2024-07-18 =
* **pre_get_posts** hook replaced with **template_redirect** action
= 1.9.6 - 2024-07-16 =
* WordPress 6.6 compatible
* **sitemap** query var renamed to **inner_sitemap**
= 1.9.5 - 2024-07-09 =
* Paginated Sitemap with Multilingual plugins issue fixed
* Polylang displaying Not Translatable Post Types issue fixed. Thanks to Adrien Tay Pamart
= 1.9.4 - 2024-06-24 =
* Adding Custom Sitemaps for Sitemap Index feature added
* Static Sitemap File detector added
* **sgg_additional_index_sitemaps** filter data structure changed
= 1.9.3 - 2024-06-18 =
* Links Per Page issue with Plain Permalinks fixed
= 1.9.2 - 2024-06-17 =
* Sitemap Index: Separate Links Per Page feature added
* Links Per Page settings added
* Default Sitemap Structure changed to Sitemap Index
* Include Custom Post Types issue fixed
* WordPress 6.5.4 compatible
= 1.9.1 - 2024-06-04 =
* Excluding Archives from Sitemap issue fixed
* Excluding Pages from Sitemap issue fixed
= 1.9.0 - 2024-05-29 =
* Multilingual Sitemap Index with all language Sitemaps aadded
* Multilingual Sitemaps duplicating URLs issues fixed
* Multilingual Sitemaps caching issue fixed
* Authors Sitemap displaying none-author Users issue fixed
= 1.8.14 - 2024-05-22 =
* Empty Additional URLs warning fixed
= 1.8.13 - 2024-05-22 =
* Sitemap Index Queries optimized
* Conflict with YOAST SEO Sitemaps fixed
= 1.8.12 - 2024-05-16 =
* **sgg_additional_index_sitemaps** filter implemented for adding Custom Sitemaps to Sitemap Index
= 1.8.11 - 2024-05-08 =
* WordPress 6.5.3 compatible
= 1.8.10 - 2024-04-23 =
* Webserver Configuration section added for NGINX servers
= 1.8.9 - 2024-04-11 =
* WordPress 6.5.2 compatible
* Child Posts incorrect URL issue fixed
= 1.8.8 - 2024-04-04 =
* XML Sitemap: Enable/Disable Sitemap feature added
* Taxonomy, Archive, and Author queries optimized
= 1.8.7 - 2024-03-28 =
* Google News: Include Older Posts feature added
* Google News: Posts older than 48 hours excluded from Sitemap by default
* XML Sitemaps, Google News, Image Sitemap, Video Sitemap: Queries optimized
* Meta Box styles conflict fixed
= 1.8.6 - 2024-03-19 =
* WordPress 6.5 compatible
* Plugin Preview enabled
* Language files updated
= 1.8.5 - 2024-03-15 =
* IndexNow Check API Key feature added
* IndexNow Change API Key feature added
* Rank Math SEO noindex Pages, Posts excluded from Sitemaps
* Rank Math SEO noindex Categories, Taxonomies excluded from Sitemaps
* **sgg_sitemap_exclude_single_term** filter added for excluding single Term from Sitemap
* Deprecated Ping Search Engines feature removed
* Deprecated Ping Google News feature removed
* Deprecated Ping Google News when Post Status changed option removed
= 1.8.4 - 2024-03-04 =
* Added Settings **Patch** for Custom Post Type and Taxonomies
* PHP 8.2 deprecated creating Dynamic Properties error fixed
* Media Sitemap Settings dependency logic improved
= 1.8.3 - 2024-02-23 =
* FooGallery compatibility added
* **sgg_indexnow_api_key** filter added for customizing IndexNow API Key
= 1.8.2 - 2024-02-21 =
* IndexNow Protocol added for indexing Microsoft Bing, Seznam.cz, Naver, and Yandex
* IndexNow automatically ping feature added when Post published and saved
= 1.8.1 - 2024-02-14 =
* Generating XML Sitemap issue fixed
= 1.8.0 - 2024-02-14 =
* Added new features:
-- Import Settings
-- Export Settings
* **sgg_disable_xml_sitemap** filter added for disabling XML Sitemap
* Add Post Meta Box applied only for Public Post Types
* Gutenberg Plugin Sidebar error fixed
= 1.7.11 - 2024-02-08 =
* Documentation links added
= 1.7.10 - 2024-01-26 =
* Last Modified Datetime field added to Additional URLs
* **xml_sitemap_news_language** filter added for customizing Google News Language
= 1.7.9 - 2024-01-18 =
* Image Sitemap: Skipping URLs with query parameters issue fixed
* PHP 8.2 compatibility improved
= 1.7.8 - 2024-01-12 =
* **xml_sitemap_include_post** filter added for customizing Post inclusion in Sitemap
* Pro Version: Page/Post Custom Sitemap Options feature added:
-- Exclude from Sitemap
-- Post Priority
-- Post Frequency
= 1.7.7 - 2024-01-05 =
* Readme updated
= 1.7.6 - 2024-01-03 =
* UI/UX improvements
= 1.7.5 - 2023-12-22 =
* **sitemap_xsl_template_path** filter added for customizing XSL Template path
= 1.7.4 - 2023-12-15 =
* Sitemap Index URLs issue with Plain Permalinks fixed
* Choose Sitemap Structure settings improved
* WordPress 6.4.2 compatible
= 1.7.3 - 2023-12-04 =
* All `pre_get_posts` filters removed from Sitemap Queries
* Inner Sitemaps displaying issue with other Sitemap plugins fixed
= 1.7.2 - 2023-11-15 =
* Include Pages option added to Google News Settings
* Page, Post, Term Priority and Frequency filters added, thanks to @mosterojei
= 1.7.1 - 2023-11-10 =
* WordPress 6.4.1 compatible
* Taxonomy Settings removed from Google News
* Pro Version: Exclude Categories and Tags feature added. Thanks to @vladynol
= 1.7.0 - 2023-11-07 =
* Image Sitemap added to Sitemap Index
* Video Sitemap added to Sitemap Index
* Adding Google News to robots.txt feature added
* Adding Image and Video Sitemaps to robots.txt feature added
= 1.6.7 - 2023-11-06 =
* WordPress 6.4 compatible
* Settings issue for WordPress versions older than 5.5.0 fixed. Thanks to @stephanie0000
= 1.6.6 - 2023-10-30 =
* Minor bug fixes
= 1.6.5 - 2023-10-06 =
* Sitemap issue with Plain Permalinks fixed
* SimpleXMLElement replaced with DOMDocument for better performance
= 1.6.4 - 2023-10-04 =
* Multilingual Sitemap URLs for WPML, Polylang, and TranslatePress outputted in Settings
* TranslatePress removing XSL Template issue fixed. Thanks to @sunlight1976
= 1.6.3 - 2023-09-28 =
* Multiple Sitemaps by Sitemap Index feature moved from Pro to Free version
* PolyLang secondary languages issue fixed
* TranslatePress compatibility improved
= 1.6.2 - 2023-09-19 =
* get_home_url() changed to get_site_url() for XSL templates. Thanks to @bretzsofas
* Disabled auto-generated WP Sitemaps
= 1.6.1 - 2023-09-11 =
* Readme updated
= 1.6.0 - 2023-09-01 =
* WordPress 6.3.1 compatible
* Pro Version: Split Sitemaps into multiple Sitemap by Sitemap Index feature added
* Pro Version: Image Sitemap - Exclude Broken Images feature added
= 1.5.6 - 2023-08-16 =
* Admin Notices added
= 1.5.5 - 2023-08-07 =
* WordPress 6.3 compatible
* Pro Version: HTML Sitemap Widget - Show Featured Image, Show Excerpt, Show Date, Date Format options added
= 1.5.4 - 2023-08-01 =
* Video Sitemap: Player_loc URL escaping issue fixed. Thanks to @track77
= 1.5.3 - 2023-07-20 =
* Conflict with older Pro Version fixed
= 1.5.2 - 2023-07-13 =
* Google News: <news:news> metadata is removed for posts older than 48 hours. Thanks to @dima2duo
* Video Sitemap: Video Link combined with Video Title for better view
* Video Sitemap: Description length is limited to 300 characters for better view
= 1.5.1 - 2023-07-11 =
* `sgg_sitemap_post_media_urls` filter added to modify Media Sitemap URLs
* Advanced Settings features improved
= 1.5.0 - 2023-07-04 =
* Dashboard Sitemap Settings escaping issues fixed
* Google News > Post Title escaping issues fixed
* Sitemap > Last Modified Date output format changed to ISO 8601
* Google News > Publication Date output format changed to ISO 8601
= 1.4.9 - 2023-06-20 =
* Plugin deactivation link removed when Pro Version is activated
* Toolbar actions improved
= 1.4.8 - 2023-06-09 =
* Yoast SEO noindex Categories, Taxonomies excluded from Sitemaps
= 1.4.7 - 2023-06-02 =
* Yoast SEO noindex Pages, Posts excluded from Sitemaps
* Video & Image Sitemap styles improved
* Pro Version: YouTube checking API Key option added
* Pro Version: YouTube API Data Caching feature added
= 1.4.6 - 2023-05-27 =
* Sitemaps styles improved
* Older PHP versions (7.3) support improved
= 1.4.5 - 2023-05-15 =
* Sitemaps restyled
* Image Sitemap: Image Preview column added
= 1.4.4 - 2023-05-07 =
* Plugin name changed
= 1.4.3 - 2023-05-03 =
* Cache Sitemaps feature added
* Caching Timeout option added
* Last Cached Time information block added
* Clear Cache added
* Google News date format changed
* Pro Version: Smart Caching feature added
= 1.4.2 - 2023-04-23 =
* Pro Version: Featured Images option added
* Pro Version: WooCommerce Gallery feature added
= 1.4.1 - 2023-04-22 =
* MediaSitemap syntax error fixed
= 1.4.0 - 2023-04-18 =
* Image Sitemap feature added
* Video Sitemap feature added
* Sitemap Content Options improved
= 1.3.5 - 2023-04-01 =
* HTML Sitemap shortcode improved
= 1.3.4 - 2023-03-26 =
* Security Update
= 1.3.3 - 2023-03-22 =
* WordPress 6.2 compatible
= 1.3.2 - 2023-03-08 =
* Scheduled posts removed from Sitemaps
* Additional URLs saving issue fixed
= 1.3.1 - 2023-03-06 =
* Save Changes issue fixed
* Ping Google News issue fixed
= 1.3.0 - 2023-03-03 =
* Help-bar with Tools, Previews, Tips, and Links added
* Automatically ping Google News feature added
* Ping Google News when Post Status changed feature added
* User-Friendly Interface improvements
= 1.2.8 - 2023-02-25 =
* Plugin name changed
= 1.2.7 - 2023-02-22 =
* Pro Features added
= 1.2.6 - 2023-02-18 =
* Minor bug fixes
= 1.2.5 - 2023-02-10 =
* Google News excluding Posts issue fixed
= 1.2.4 - 2023-02-06 =
* Pro Features added
= 1.2.3 - 2023-01-20 =
* Polylang displaying Home Page URL issue fixed
= 1.2.2 - 2022-12-29 =
* Minor bug fixes
= 1.2.1 - 2022-11-27 =
* Google News Sitemap added
* Google News custom Publication name feature added
* Google News custom Sitemap URL feature added
= 1.2.0 - 2022-11-03 =
* Pro Version added
= 1.1.2 - 2022-10-30 =
* WordPress 6.1 compatible
= 1.1.1 - 2022-09-17 =
* Minimum PHP Version downgraded
= 1.1.0 - 2022-07-29 =
* Front page last modified time issue fixed
= 1.0.7 - 2022-05-13 =
* WordPress 6.0 compatible
= 1.0.6 - 2022-02-07 =
* WordPress 5.9 compatible
= 1.0.5 - 2021-11-21 =
* WordPress compatibility update
= 1.0.4 - 2021-10-03 =
* Bug fixes.
= 1.0.3 - 2021-07-08 =
* WordPress 5.8 compatible
= 1.0.2 - 2021-03-13 =
* WordPress 5.7 compatible
= 1.0.1 - 2021-02-21 =
* Bug fixes
= 1.0.0 - 2021-02-17 =
* Release

View File

@@ -0,0 +1,25 @@
<?php
/**
* @var $args
*/
?>
<div>
<input type="text" name="<?php echo esc_attr( $args['name'] ); ?>-autocomplete" class="sgg-autocomplete grim-input <?php echo esc_attr( $args['class'] ?? '' ); ?>" size="50"
data-target="<?php echo esc_attr( $args['name'] ); ?>"
data-type="<?php echo esc_attr( $args['type'] ?? '' ); ?>"
placeholder="<?php echo esc_attr__( 'Type to Search...', 'xml-sitemap-generator-for-google' ); ?>">
<input type="hidden" id="<?php echo esc_attr( $args['name'] ); ?>"
name="<?php echo esc_attr( $args['name'] ); ?>"
value="<?php echo esc_attr( stripslashes( $args['value'] ) ); ?>">
<div class="expand <?php echo esc_attr( $args['class'] ?? '' ); ?>">
<table class="grim-table wp-list-table widefat fixed striped">
<tbody class="widefat striped sgg-autocomplete-terms">
</tbody>
</table>
<a href="#" class="grim-button grim-mt-10 secondary grim-expand-toggle">
<span>Show More</span>
</a>
</div>
</div>

View File

@@ -0,0 +1,41 @@
<?php
/**
* @var $args
*/
?>
<?php
$is_default = ! empty( $args['is_default'] );
$name = esc_attr( $args['name'] );
$class = esc_attr( $args['class'] ?? '' );
$value = esc_attr( $args['value'] );
$label = esc_html( $args['label'] );
?>
<label
class="<?php echo ! $is_default ? esc_attr( "grim-toggle {$class}" ) : ''; ?>"
for="<?php echo esc_attr( $name ); ?>">
<input type="checkbox"
name="<?php echo esc_attr( $name ); ?>"
id="<?php echo esc_attr( $name ); ?>"
value="1"
class="<?php echo $is_default ? esc_attr( "grim-default-checkbox {$class}" ) : esc_attr( "grim-toggle-input {$class}" ); ?>"
<?php
checked( $value, '1' );
if ( ! empty( $args['data'] ) ) {
foreach ( $args['data'] as $attr => $val ) {
echo " data-{$attr}='" . esc_attr( $val ) . "' ";
}
}
?> />
<?php if ( $is_default ) : ?>
<?php echo esc_html( $label ); ?>
<?php else : ?>
<span class="grim-toggle-slider"></span>
<span class="grim-toggle-label" data-search-id="<?php echo esc_attr( $name ); ?>">
<?php echo esc_html( $label ); ?>
</span>
<?php endif; ?>
</label>

View File

@@ -0,0 +1,10 @@
<?php
/**
* @var $args
*/
?>
<label for="<?php echo esc_attr( $args['name'] ); ?>" class="<?php echo esc_attr( $args['class'] ?? '' ); ?>"><?php echo esc_html( $args['label'] ?? '' ); ?></label>
<input type="color" id="<?php echo esc_attr( $args['name'] ); ?>"
name="<?php echo esc_attr( $args['name'] ); ?>" size="50"
class="<?php echo esc_attr( $args['class'] ?? '' ); ?>"
value="<?php echo esc_attr( $args['value'] ); ?>"/>

View File

@@ -0,0 +1,44 @@
<?php
/**
* @var $args
*/
?>
<tr>
<td class="<?php echo esc_attr( $args['class'] ?? '' ); ?>">
<?php echo esc_html( $args['title'] ?? '' ); ?>
</td>
<td>
<div class="grim-select grim-select-default" data-name="<?php echo esc_attr( $args['name'] ); ?>">
<div class="grim-select__trigger">
<span>
<?php
if ( $args['value'] === '1' ) {
esc_html_e( 'Include', 'xml-sitemap-generator-for-google' );
} else {
esc_html_e( 'Exclude', 'xml-sitemap-generator-for-google' );
}
?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<div class="grim-option <?php echo $args['value'] === '1' ? 'selected' : ''; ?>" data-value="1">
<?php esc_html_e( 'Include', 'xml-sitemap-generator-for-google' ); ?>
</div>
<div class="grim-option <?php echo $args['value'] === '0' || $args['value'] === false ? 'selected' : ''; ?>" data-value="0">
<?php esc_html_e( 'Exclude', 'xml-sitemap-generator-for-google' ); ?>
</div>
</div>
</div>
<!-- скрытый настоящий select -->
<select id="<?php echo esc_attr( $args['name'] ); ?>" name="<?php echo esc_attr( $args['name'] ); ?>" class="grim-hidden-select" hidden>
<option value="1" <?php selected( $args['value'], '1' ); ?>>
<?php esc_html_e( 'Include', 'xml-sitemap-generator-for-google' ); ?>
</option>
<option value="0" <?php selected( $args['value'], '0' ); selected( $args['value'], false ); ?>>
<?php esc_html_e( 'Exclude', 'xml-sitemap-generator-for-google' ); ?>
</option>
</select>
</td>
</tr>

View File

@@ -0,0 +1,45 @@
<?php
/**
* @var $args
*/
use GRIM_SG\PTSettings;
$options = [
PTSettings::$ALWAYS => __( 'Always', 'xml-sitemap-generator-for-google' ),
PTSettings::$HOURLY => __( 'Hourly', 'xml-sitemap-generator-for-google' ),
PTSettings::$DAILY => __( 'Daily', 'xml-sitemap-generator-for-google' ),
PTSettings::$WEEKLY => __( 'Weekly', 'xml-sitemap-generator-for-google' ),
PTSettings::$MONTHLY => __( 'Monthly', 'xml-sitemap-generator-for-google' ),
PTSettings::$YEARLY => __( 'Yearly', 'xml-sitemap-generator-for-google' ),
PTSettings::$NEVER => __( 'Never', 'xml-sitemap-generator-for-google' ),
];
$current = $args['value'] ?? PTSettings::$NEVER;
?>
<div class="grim-select grim-select-default" data-name="<?php echo esc_attr( $args['name'] ); ?>">
<div class="grim-select__trigger">
<span>
<?php echo esc_html( $options[ $current ] ?? __( 'Never', 'xml-sitemap-generator-for-google' ) ); ?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<?php foreach ( $options as $value => $label ) : ?>
<div class="grim-option <?php echo (string) $current === (string) $value ? 'selected' : ''; ?>" data-value="<?php echo esc_attr( $value ); ?>">
<?php echo esc_html( $label ); ?>
</div>
<?php endforeach; ?>
</div>
</div>
<select id="<?php echo esc_attr( $args['name'] ); ?>"
name="<?php echo esc_attr( $args['name'] ); ?>"
class="grim-hidden-select"
hidden>
<?php foreach ( $options as $value => $label ) : ?>
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $current, $value ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endforeach; ?>
</select>

View File

@@ -0,0 +1,20 @@
<?php
/**
* @var $args
*/
?>
<label for="<?php echo esc_attr( $args['name'] ?? '' ); ?>"
data-search-id="<?php echo esc_attr( $args['name'] ?? '' ); ?>"
class="<?php echo esc_attr( $args['class'] ?? '' ); ?>">
<?php echo esc_html( $args['label'] ?? '' ) ; ?>
</label>
<input type="<?php echo esc_attr( $args['type'] ?? 'text' ); ?>" id="<?php echo esc_attr( $args['name'] ?? '' ); ?>"
name="<?php echo esc_attr( $args['name'] ?? '' ); ?>" size="50"
class="<?php echo esc_attr( $args['class'] ?? '' ); ?>"
placeholder="<?php echo esc_attr( $args['placeholder'] ?? '' ); ?>"
value="<?php echo esc_attr( $args['value'] ); ?>"/>
<?php if ( ! empty( $args['description'] ) ) { ?>
<span class="field-description <?php echo esc_attr( $args['class'] ?? '' ); ?>"><?php echo wp_kses_post( $args['description'] ); ?></span>
<?php
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* @var $args
*/
use GRIM_SG\Dashboard;
?>
<tr>
<td><?php echo esc_html( $args['title'] ?? '' ); ?></td>
<td>
<div class="grim-select grim-select-default" data-name="<?php echo esc_attr( $args['option'] ); ?>_include">
<div class="grim-select__trigger">
<span>
<?php
if ( $args['data']->include === '1' ) {
esc_html_e( 'Include', 'xml-sitemap-generator-for-google' );
} else {
esc_html_e( 'Exclude', 'xml-sitemap-generator-for-google' );
}
?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<div class="grim-option <?php echo $args['data']->include === '1' ? 'selected' : ''; ?>" data-value="1">
<?php esc_html_e( 'Include', 'xml-sitemap-generator-for-google' ); ?>
</div>
<div class="grim-option <?php echo $args['data']->include === '0' ? 'selected' : ''; ?>" data-value="0">
<?php esc_html_e( 'Exclude', 'xml-sitemap-generator-for-google' ); ?>
</div>
</div>
</div>
<select id="<?php echo esc_attr( $args['option'] ); ?>_include"
name="<?php echo esc_attr( $args['option'] ); ?>_include"
class="grim-hidden-select"
hidden>
<option value="1" <?php selected( $args['data']->include, '1' ); ?>>
<?php esc_html_e( 'Include', 'xml-sitemap-generator-for-google' ); ?>
</option>
<option value="0" <?php selected( $args['data']->include, '0' ); ?>>
<?php esc_html_e( 'Exclude', 'xml-sitemap-generator-for-google' ); ?>
</option>
</select>
</td>
<td><?php Dashboard::render_priority_field( $args['option'] . '_priority', $args['data']->priority ); ?></td>
<td><?php Dashboard::render_frequency_field( $args['option'] . '_frequency', $args['data']->frequency ); ?></td>
</tr>

View File

@@ -0,0 +1,38 @@
<?php
/**
* @var $args
*/
?>
<div class="grim-select grim-select-default" data-name="<?php echo esc_attr( $args['name'] ); ?>">
<div class="grim-select__trigger">
<span>
<?php
$value = $args['value'] ?? '0';
echo esc_html( number_format( (int) $value / 10, 1 ) );
?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<?php for ( $i = 0; $i <= 10; $i++ ) :
$label = number_format( $i / 10, 1 );
?>
<div class="grim-option <?php echo (string) $value === (string) $i ? 'selected' : ''; ?>" data-value="<?php echo esc_attr( $i ); ?>">
<?php echo esc_html( $label ); ?>
</div>
<?php endfor; ?>
</div>
</div>
<select id="<?php echo esc_attr( $args['name'] ); ?>"
name="<?php echo esc_attr( $args['name'] ); ?>"
class="grim-hidden-select"
hidden>
<?php for ( $i = 0; $i <= 10; $i++ ) :
$label = number_format( $i / 10, 1 );
?>
<option value="<?php echo esc_attr( $i ); ?>" <?php selected( (string) $value, (string) $i ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endfor; ?>
</select>

View File

@@ -0,0 +1,13 @@
<?php
/**
* @var $args
*/
?>
<input type="radio" name="<?php echo esc_attr( $args['name'] ); ?>" id="<?php echo esc_attr( $args['id'] ); ?>" value="<?php echo esc_attr( $args['value'] ); ?>" <?php checked( esc_attr( $args['value'] ), esc_attr( $args['current_value'] ) ); ?> />
<label for="<?php echo esc_attr( $args['id'] ); ?>"><?php echo esc_html( $args['label'] ); ?>
<?php if ( ! empty( $args['description'] ) ) { ?>
<div class="field-description"><?php echo wp_kses_post( $args['description'] ); ?></div>
<?php
} ?>
</label>

View File

@@ -0,0 +1,35 @@
<?php
/**
* @var $args
*/
?>
<div class="grim-select-label <?php echo esc_attr( $args['class'] ); ?>" data-search-id="<?php echo esc_attr( $args['name'] ?? '' ); ?>">
<?php echo esc_html( $args['label'] ); ?>
</div>
<div class="grim-select <?php echo esc_attr( $args['select_size'] ?? 'grim-select-default' ); ?> <?php echo esc_attr( $args['class'] ); ?>" data-name="<?php echo esc_attr( $args['name'] ); ?>">
<div class="grim-select__trigger">
<span>
<?php echo esc_html( $args['options'][$args['value']] ?? __( 'None', 'xml-sitemap-generator-for-google' ) ); ?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<div class="grim-option" data-value="">
<?php esc_html_e( 'None', 'xml-sitemap-generator-for-google' ); ?>
</div>
<?php foreach ( $args['options'] as $value => $label ) { ?>
<div class="grim-option <?php echo $args['value'] === $value ? 'selected' : ''; ?>" data-value="<?php echo esc_attr( $value ); ?>">
<?php echo esc_html( $label ); ?>
</div>
<?php } ?>
</div>
</div>
<select id="<?php echo esc_attr( $args['name'] ); ?>" name="<?php echo esc_attr( $args['name'] ); ?>" class="grim-hidden-select" hidden>
<option value="" <?php selected( $args['value'], '' ); ?>><?php esc_html_e( 'None', 'xml-sitemap-generator-for-google' ); ?></option>
<?php foreach ( $args['options'] as $value => $label ) { ?>
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value , $args['value'] ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php } ?>
</select>

View File

@@ -0,0 +1,55 @@
<?php
/**
* @var $args
*/
use GRIM_SG\Dashboard;
$languages = sgg_get_languages();
$wpml_languages = apply_filters( 'wpml_active_languages', array() );
$input_class = $args['input_class'] ?? '';
$input_label = $args['input_label'] ?? '';
$input_value = $args['input_value'] ?? '';
$input_name = $args['input_name'] ?? '';
$description = $args['description'] ?? '';
$button_id = $args['button_id'] ?? '';
$button_text = $args['button_text'] ?? '';
$button_name = $args['button_name'] ?? '';
$placeholder = $args['placeholder'] ?? '';
?>
<div class="grim-previews-url">
<p>
<?php
Dashboard::render(
'fields/input.php',
array(
'placeholder' => $placeholder,
'name' => $input_name,
'value' => $input_value,
'label' => $input_label,
'class' => $input_class,
)
);
?>
</p>
<div class="video-sitemap-depended">
<input type="hidden" name="<?php echo esc_attr( $button_name ); ?>" value="">
<button type="submit" id="<?php echo esc_attr( $button_id ); ?>" class="grim-button grim-submit white video-sitemap-depended">
<span>
<?php echo esc_html( $button_text ); ?>
</span>
</button>
</div>
</div>
<div class="<?php echo esc_attr( $args['class'] ?? '' ); ?>">
<?php echo esc_html( $args['label'] ?? '' ); ?>
<span class="grim-previews-url-desc <?php echo esc_attr( $args['input_class'] ?? '' ); ?>">
<?php
if ( ! empty( $description ) ) {
echo wp_kses_post( $description );
}
?>
</span>
</div>

View File

@@ -0,0 +1,44 @@
<?php
/**
* @var $args
*/
$settings = $args['settings'] ?? new stdClass();
?>
<div class="grim-header">
<div class="grim-section grim-nav">
<div class="grim-nav-wrapper">
<div class="grim-nav-tab-wrapper">
<nav class="grim-nav-tab nav-tab-wrapper">
<a href="#" class="grim-nav-tab-item nav-tab nav-tab-active" data-id="general"><i class="grim-icon-home"></i><?php esc_html_e( 'General', 'xml-sitemap-generator-for-google' ); ?></a>
<a href="#" class="grim-nav-tab-item nav-tab" data-id="google-news"><i class="grim-icon-google"></i><?php esc_html_e( 'Google News', 'xml-sitemap-generator-for-google' ); ?></a>
<a href="#" class="grim-nav-tab-item nav-tab" data-id="image-sitemap"><i class="grim-icon-image"></i><?php esc_html_e( 'Image Sitemap', 'xml-sitemap-generator-for-google' ); ?></a>
<a href="#" class="grim-nav-tab-item nav-tab" data-id="video-sitemap"><i class="grim-icon-play-circle"></i><?php esc_html_e( 'Video Sitemap', 'xml-sitemap-generator-for-google' ); ?></a>
<a href="#" class="grim-nav-tab-item nav-tab" data-id="advanced"><i class="grim-icon-sliders-horizontal"></i><?php esc_html_e( 'Advanced', 'xml-sitemap-generator-for-google' ); ?></a>
</nav>
</div>
<div class="grim-settings-search">
<div class="grim-settings-search-input-wrapper">
<input type="search" class="grim-input" id="grim-settings-search-input" placeholder="<?php esc_attr_e( 'Search settings...', 'xml-sitemap-generator-for-google' ); ?>">
<div class="grim-settings-search-cancel grim-button white">
<span><?php esc_html_e( 'Cancel', 'xml-sitemap-generator-for-google' ); ?></span>
</div>
</div>
<div class="grim-search-results" id="grim-search-results">
<div class="grim-search-results-list"></div>
</div>
</div>
<div class="grim-nav-wrapper-actions">
<div class="grim-search-action">
<div class="grim-search-action-btn">
<i class="grim-icon-search"></i>
</div>
</div>
<button type="submit" name="submit" class="grim-button secondary">
<span><?php esc_html_e( 'Save changes', 'xml-sitemap-generator-for-google' ); ?></span>
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,101 @@
<?php
/**
* @var $args
*/
use GRIM_SG\Dashboard;
$sitemap_type = $args['sitemap_type'] ?? 'sitemap_xml';
$sitemap_url = $args['sitemap_url'] ?? '';
$languages = sgg_get_languages( true );
$wpml_languages = apply_filters( 'wpml_active_languages', array() );
$input_class = $args['input_class'] ?? '';
$input_label = $args['input_label'] ?? '';
$input_value = $args['input_value'] ?? '';
$input_name = $args['input_name'] ?? '';
$notice_show = $args['notice_show'] ?? false;
?>
<div class="grim-previews-url">
<p>
<?php
Dashboard::render(
'fields/input.php',
array(
'name' => $input_name,
'value' => $input_value,
'label' => $input_label,
'class' => $input_class,
)
);
?>
</p>
<a href="<?php echo esc_url( sgg_get_sitemap_url( $sitemap_url, $sitemap_type ) ); ?>" class="grim-button white <?php echo esc_attr( $input_class ); ?>" target="_blank">
<span>
<?php esc_html_e( 'Preview', 'xml-sitemap-generator-for-google' ); ?>
</span>
</a>
</div>
<div class="<?php echo esc_attr( $args['class'] ?? '' ); ?>">
<?php echo esc_html( $args['label'] ?? '' ); ?>
<span class="grim-previews-url-desc">
<?php echo esc_url( sgg_get_sitemap_url( $sitemap_url, $sitemap_type ) ); ?>
</span>
<?php if ( ! empty( $languages ) || ! empty( $wpml_languages ) ) { ?>
<p class="<?php echo esc_attr( $args['class'] ?? '' ); ?> grim-preview-multilang grim-mt-10">
<span class="grim-preview-multilang-label"><?php echo esc_html( $args['languages_label'] ?? '' ); ?></span>
<?php
foreach ( $languages as $language ) {
?>
<br>
<a href="<?php echo esc_url( sgg_get_sitemap_url( "{$language}/{$sitemap_url}", $sitemap_type ) ); ?>" class="grim-mb-5" target="_blank">
<?php echo esc_url( sgg_get_sitemap_url( "{$language}/{$sitemap_url}", $sitemap_type ) ); ?>
</a>
<?php
}
if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {
foreach ( $wpml_languages as $language ) {
if ( apply_filters( 'wpml_default_language', null ) === $language['code'] ) {
continue;
}
$url = strpos( $language['url'], '?lang=' ) !== false
? str_replace( '?lang=', "{$sitemap_url}?lang=", $language['url'] )
: trim( $language['url'], '/' ) . "/$sitemap_url";
?>
<br>
<a href="<?php echo esc_url( $url ); ?>" target="_blank" class="grim-mb-5">
<?php echo esc_url( $url ); ?>
</a>
<?php
}
}
?>
</p>
<?php if ( 'sitemap_xml' === $sitemap_type ) { ?>
<p class="<?php echo esc_attr( $args['class'] ?? '' ); ?> grim-preview-multilang">
<span class="grim-preview-multilang-label"><?php esc_html_e( 'Multilingual Sitemap Index:', 'xml-sitemap-generator-for-google' ); ?></span>
<br>
<a href="<?php echo esc_url( site_url( 'multilingual-sitemap.xml' ) ); ?>" target="_blank">
<?php echo esc_url( site_url( 'multilingual-sitemap.xml' ) ); ?>
</a>
</p>
<?php } ?>
<?php } ?>
<?php
if ( $notice_show ) {
Dashboard::render(
'partials/sitemap-detector.php',
array(
'sitemap_url' => $sitemap_url,
)
);
}
?>
</div>

View File

@@ -0,0 +1,8 @@
<div class="pro-title-badge">
<span class="pro-title-badge-title"><i class="grim-icon-base-tooltip"></i><?php esc_html_e( 'This feature is available on Premium version', 'xml-sitemap-generator-for-google' ); ?></span>
<a href="<?php echo esc_url( sgg_get_pro_url() ); ?>" class="grim-button secondary" target="_blank">
<span>
<?php esc_html_e( 'Get Now', 'xml-sitemap-generator-for-google' ); ?>
</span>
</a>
</div>

View File

@@ -0,0 +1,6 @@
<?php
/**
* @var $args
*/
?>
<div class="pro-overlay"></div>

View File

@@ -0,0 +1,35 @@
<?php
/**
* @var $args
*/
wp_enqueue_style( 'sgg-rate-banner' );
wp_enqueue_style( 'sgg-icons' );
?>
<div class="grim-container grim-rate-container notice <?php echo esc_attr( $args['wrapper_classes'] ?? '' ); ?>">
<div class="grim-section grim-rate grim-notice-data <?php echo esc_attr( $args['notice_class'] ?? '' ); ?>" data-notice="<?php echo esc_attr( $args['data_notice'] ); ?>">
<?php if ( ! empty( $args['label'] ) ) : ?>
<h3 class="grim-rate-title"><?php echo wp_kses_post( $args['label'] ); ?></h3>
<?php endif; ?>
<p class="grim-rate-description">
<?php echo wp_kses_post( $args['description'] ) ?? ''; ?>
</p>
<div class="grim-rate-actions">
<?php if( ! empty( $args['extra_btn_url'] ) ) : ?>
<a class="grim-button white <?php echo esc_attr( $args['extra_btn_class'] ); ?>" target="_blank" href="<?php echo esc_url( $args['extra_btn_url'] ); ?>">
<span><?php echo wp_kses_post( $args['extra_btn_text'] ); ?></span>
</a>
<?php else: ?>
<a class="grim-button white sgg-notice">
<span><?php esc_html_e( 'Dismiss', 'xml-sitemap-generator-for-google' ); ?></span>
</a>
<?php endif; ?>
<a href="<?php echo esc_url( $args['button_url'] ); ?>" target="_blank" class="grim-button secondary sgg-notice">
<span><?php echo esc_html( $args['button_text'] ) ?><i class="grim-icon-arrow-right"></i></span>
</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,225 @@
<?php
use GRIM_SG\Dashboard;
$settings = $args['settings'] ?? new stdClass();
$previews = array();
$tools = array();
// XML Sitemap
if ( $settings->enable_sitemap ) {
$previews[] = array(
'label' => __( 'XML Sitemap', 'xml-sitemap-generator-for-google' ),
'url' => sgg_get_sitemap_url( $settings->sitemap_url, 'sitemap_xml' ),
);
}
// HTML Sitemap (Pro)
if ( sgg_pro_enabled() && $settings->enable_html_sitemap ) {
$previews[] = array(
'label' => __( 'HTML Sitemap', 'xml-sitemap-generator-for-google' ),
'url' => sgg_get_sitemap_url( $settings->html_sitemap_url, 'sitemap_html' ),
);
}
// Google News
if ( $settings->enable_google_news ) {
$previews[] = array(
'label' => __( 'Google News', 'xml-sitemap-generator-for-google' ),
'url' => sgg_get_sitemap_url( $settings->google_news_url, 'google_news' ),
);
}
// Image Sitemap
if ( $settings->enable_image_sitemap ) {
$previews[] = array(
'label' => __( 'Image Sitemap', 'xml-sitemap-generator-for-google' ),
'url' => sgg_get_sitemap_url( $settings->image_sitemap_url, 'image_sitemap' ),
);
}
// Video Sitemap
if ( $settings->enable_video_sitemap ) {
$previews[] = array(
'label' => __( 'Video Sitemap', 'xml-sitemap-generator-for-google' ),
'url' => sgg_get_sitemap_url( $settings->video_sitemap_url, 'video_sitemap' ),
);
}
// IndexNow
if ( $settings->enable_indexnow ) {
$tools[] = array(
'name' => 'sgg-indexnow',
'label' => __( 'Ping IndexNow Protocol', 'xml-sitemap-generator-for-google' ),
'class' => 'white',
);
}
// Flush Rewrite Rules
$tools[] = array(
'name' => 'sgg-flush-rewrite-rules',
'label' => __( 'Flush Rewrite Rules', 'xml-sitemap-generator-for-google' ),
'class' => 'white',
);
// Clear Cache
if ( $settings->enable_cache ) {
$tools[] = array(
'name' => 'sgg-clear-cache',
'label' => __( 'Clear Sitemaps Cache', 'xml-sitemap-generator-for-google' ),
'class' => 'delete',
);
}
$plugin_links = array(
array(
'title' => esc_html__( 'Documentation', 'xml-sitemap-generator-for-google' ),
'icon' => 'grim-icon-file-text',
'link' => 'https://wpgrim.com/docs/google-xml-sitemaps-generator/?utm_source=sgg-plugin&utm_medium=documentation&utm_campaign=xml_sitemap',
),
array(
'title' => esc_html__( 'Support Forum', 'xml-sitemap-generator-for-google' ),
'icon' => 'grim-icon-help',
'link' => esc_url( sgg_get_support_url() ),
),
array(
'title' => sprintf(
/* translators: %s: Rating stars */
esc_html__( 'Rate %s', 'xml-sitemap-generator-for-google' ),
'<strong>' . esc_html__( '★★★★★', 'xml-sitemap-generator-for-google' ) . '</strong>'
),
'icon' => 'grim-icon-star',
'link' => esc_url( sgg_get_review_url() ),
'class' => 'grim-rate-button',
),
);
if ( sgg_pro_enabled() ) {
array_unshift(
$plugin_links,
array(
'title' => esc_html__( 'Account & Support', 'xml-sitemap-generator-for-google' ),
'icon' => 'grim-icon-user',
'link' => 'https://wpgrim.com/account?utm_source=sgg-plugin&utm_medium=account&utm_campaign=xml_sitemap',
)
);
}
$footer_links = array(
array(
'title' => esc_html__( 'Google Search Console', 'xml-sitemap-generator-for-google' ),
'link' => 'https://search.google.com/search-console',
),
array(
'title' => esc_html__( 'Google News Help Center', 'xml-sitemap-generator-for-google' ),
'link' => 'https://support.google.com/googlenews/',
),
array(
'title' => esc_html__( 'Show up in Google News', 'xml-sitemap-generator-for-google' ),
'link' => 'https://support.google.com/news/publisher-center/answer/9607025',
),
array(
'title' => esc_html__( 'IndexNow Protocol', 'xml-sitemap-generator-for-google' ),
'link' => 'https://www.indexnow.org/',
),
array(
'title' => esc_html__( 'Bing Webmaster Tools', 'xml-sitemap-generator-for-google' ),
'link' => 'https://www.bing.com/webmasters',
),
array(
'title' => esc_html__( 'Yandex Webmaster', 'xml-sitemap-generator-for-google' ),
'link' => 'https://webmaster.yandex.com/sites/',
),
array(
'title' => esc_html__( 'XML Sitemap Validator', 'xml-sitemap-generator-for-google' ),
'link' => 'https://www.xml-sitemaps.com/validate-xml-sitemap.html',
),
);
?>
<div class="grim-section">
<?php if ( ! empty( $tools ) ) : ?>
<div class="grim-sidebar-section grim-sidebar-actions">
<h3 class="grim-section-title"><?php esc_html_e( 'Tools', 'xml-sitemap-generator-for-google' ); ?></h3>
<div class="grim-sidebar-list">
<?php foreach ( $tools as $tool ) : ?>
<div class="grim-sidebar-list-item">
<div class="grim-button white <?php echo esc_attr( $tool['class'] ); ?>">
<input type="hidden" name="<?php echo esc_attr( $tool['name'] ); ?>" value="">
<input
type="submit"
id="<?php echo esc_attr( $tool['name'] ); ?>"
name="<?php echo esc_attr( $tool['name'] ); ?>-button"
value="<?php echo esc_attr( $tool['label'] ); ?>"
class="<?php echo esc_attr( $tool['class'] ); ?>"
>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php if ( ! empty( $previews ) ) : ?>
<div class="grim-sidebar-section">
<h3 class="grim-section-title"><?php esc_html_e( 'Preview', 'xml-sitemap-generator-for-google' ); ?></h3>
<div class="grim-sidebar-list">
<?php foreach ( $previews as $item ) : ?>
<div class="grim-sidebar-list-item">
<a href="<?php echo esc_url( $item['url'] ); ?>" class="grim-button white button-icon-right" target="_blank">
<span>
<?php echo wp_kses_post( $item['label'] ); ?>
<i class="grim-icon-external-link"></i>
</span>
</a>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<?php
if ( ! sgg_pro_enabled() ) {
Dashboard::render(
'partials/rate-banner.php',
array(
'description' => sprintf(
/* translators: %s: Pro version */
esc_html__( 'If you want to unlock more features, please check out our %s.', 'xml-sitemap-generator-for-google' ),
'<a href="' . esc_url( sgg_get_pro_url( 'notice' ) ) . '" target="_blank">' . esc_html__( 'Pro version', 'xml-sitemap-generator-for-google' ) . '</a>'
),
'button_text' => esc_html__( 'Read More', 'xml-sitemap-generator-for-google' ),
'button_url' => esc_url( sgg_get_pro_url( 'notice' ) ),
'data_notice' => 'sgg_buy_pro',
'notice_class' => 'grim-pro-notice grim-sidebar-notice',
)
);
}
?>
<div class="grim-sidebar-section grim-sidebar-actions">
<h3 class="grim-section-title"><?php esc_html_e( 'Useful', 'xml-sitemap-generator-for-google' ); ?></h3>
<?php foreach ( $plugin_links as $plugin_link ) : ?>
<div class="grim-sidebar-list-item grim-sidebar-actions-item">
<a class="grim-button white <?php echo ! empty( $plugin_link['class'] ) ? esc_attr( $plugin_link['class'] ) : ''; ?>" href="<?php echo esc_url( $plugin_link['link'] ); ?>" target="_blank">
<span>
<i class="<?php echo esc_attr( $plugin_link['icon'] ); ?>"></i><?php echo wp_kses_post( $plugin_link['title'] ); ?>
</span>
</a>
</div>
<?php endforeach; ?>
</div>
<div class="grim-sidebar-section">
<h3 class="grim-section-title"><?php esc_html_e( 'Links', 'xml-sitemap-generator-for-google' ); ?></h3>
<div class="grim-sidebar-links">
<?php foreach ( $footer_links as $footer_link ) : ?>
<a class="grim-sidebar-links-item" target="_blank" href="<?php echo esc_url( $footer_link['link'] ); ?>"><?php echo esc_html( $footer_link['title'] ); ?></a>
<?php endforeach; ?>
</div>
</div>
<hr>
<div class="grim-sidebar-section grim-sidebar-wrapper-info">
<div class="grim-sidebar-wrapper-info-logo">
<img src="<?php echo esc_url( plugins_url( 'assets/images/sgg-logo.svg', GRIM_SG_FILE ) ); ?>" alt="logo" width="60" height="60"/>
</div>
<div class="grim-sidebar-wrapper-info-title">
<a href="https://wpgrim.com/dynamic-xml-sitemaps-generator-for-google/?utm_source=sgg-plugin&utm_medium=footer&utm_campaign=xml_sitemap" target="_blank">Dynamic XML Sitemaps Generator For Google Pro</a>
</div>
</div>
</div>

View File

@@ -0,0 +1,28 @@
<?php
/**
* @var $args
*/
$sitemap_url = $args['sitemap_url'];
if ( file_exists( ABSPATH . $sitemap_url ) ) {
$notice_status = 'error';
$notice_message = esc_html__( 'Warning! Static Sitemap File was detected in this URL. Please remove this file from the WordPress Root Directory to use Dynamic Sitemap.', 'xml-sitemap-generator-for-google' );
} else {
$notice_status = 'success';
$notice_message = sprintf(
esc_html__( 'No static sitemap file was detected in this URL. %s', 'xml-sitemap-generator-for-google' ),
'<span>' . esc_html__( 'Above URL will open the awesome Dynamic Sitemap.', 'xml-sitemap-generator-for-google' ) . '</span>'
);
}
if ( ! empty( $sitemap_url ) && ! empty( $notice_message ) ) {
?>
<div class="grim-notice notice-<?php echo esc_html( $notice_status ); ?> inline sitemap-detector">
<i class="grim-icon-check-circle"></i>
<p>
<?php echo wp_kses_post( $notice_message ); ?>
</p>
</div>
<?php
}

View File

@@ -0,0 +1,145 @@
<?php
/**
* @var $post
*/
$exclude = get_post_meta( $post->ID, '_sitemap_exclude', true );
$priority = get_post_meta( $post->ID, '_sitemap_priority', true );
$frequency = get_post_meta( $post->ID, '_sitemap_frequency', true );
$frequency = isset( $frequency ) ? (string) $frequency : '';
$priority = isset( $priority ) ? (string) $priority : '';
$frequency_options = array(
'' => __( 'Default', 'xml-sitemap-generator-for-google' ),
'always' => __( 'Always', 'xml-sitemap-generator-for-google' ),
'hourly' => __( 'Hourly', 'xml-sitemap-generator-for-google' ),
'daily' => __( 'Daily', 'xml-sitemap-generator-for-google' ),
'weekly' => __( 'Weekly', 'xml-sitemap-generator-for-google' ),
'monthly' => __( 'Monthly', 'xml-sitemap-generator-for-google' ),
'yearly' => __( 'Yearly', 'xml-sitemap-generator-for-google' ),
'never' => __( 'Never', 'xml-sitemap-generator-for-google' ),
);
wp_enqueue_style( 'sgg-meta-box', GRIM_SG_URL . 'assets/css/meta-box.min.css', array(), GRIM_SG_VERSION );
wp_enqueue_style( 'sgg-icons', GRIM_SG_URL . 'assets/fonts/icons/style.css', array(), GRIM_SG_VERSION );
wp_enqueue_script( 'sgg-scripts', GRIM_SG_URL . 'assets/js/scripts.js', array( 'jquery' ), GRIM_SG_VERSION, true );
wp_nonce_field( 'sgg_pro_meta_box', 'sgg_pro_meta_box_nonce' );
?>
<div class="grim-section grim-section-post-meta pro-wrapper <?php echo esc_attr( sgg_pro_class() ); ?>">
<?php sgg_show_pro_badge(); ?>
<p class="grim-section-desc"><?php esc_html_e( 'Custom Sitemap Options for the Current Post such as Exclude from Sitemap, Post Priority, Post Frequency.', 'xml-sitemap-generator-for-google' ); ?></p>
<table class="grim-table wp-list-table widefat fixed striped">
<?php if ( ! apply_filters( 'xml_sitemap_disable_post_meta__exclude_sitemap', false ) ) { ?>
<tr>
<td>
<label for="_sitemap_exclude"><?php esc_html_e( 'Exclude from Sitemap', 'xml-sitemap-generator-for-google' ); ?></label>
</td>
<td>
<label for="_sitemap_exclude">
<input class="grim-default-checkbox" type="checkbox" name="_sitemap_exclude" id="_sitemap_exclude" value="1" <?php checked( $exclude, '1' ); ?> <?php disabled( ! sgg_pro_enabled() ); ?> />
</label>
</td>
</tr>
<?php } ?>
<?php if ( ! apply_filters( 'xml_sitemap_disable_post_meta__sitemap_priority', false ) ) { ?>
<tr>
<td>
<label for="_sitemap_priority"><?php esc_html_e( 'Post Priority', 'xml-sitemap-generator-for-google' ); ?></label>
</td>
<td>
<div class="grim-select grim-select-default"
data-name="_sitemap_priority">
<div class="grim-select__trigger">
<span>
<?php
if ( $priority === '' ) {
esc_html_e( 'Default', 'xml-sitemap-generator-for-google' );
} else {
echo esc_html( number_format( (int) $priority / 10, 1 ) );
}
?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<div class="grim-option <?php echo $priority === '' ? 'selected' : ''; ?>" data-value="">
<?php esc_html_e( 'Default', 'xml-sitemap-generator-for-google' ); ?>
</div>
<?php for ( $i = 0; $i <= 10; $i++ ) :
$label = number_format( $i / 10, 1 );
?>
<div class="grim-option <?php echo (string) $priority === (string) $i ? 'selected' : ''; ?>"
data-value="<?php echo esc_attr( $i ); ?>">
<?php echo esc_html( $label ); ?>
</div>
<?php endfor; ?>
</div>
</div>
<select id="_sitemap_priority"
name="_sitemap_priority"
class="grim-hidden-select"
hidden>
<option value="" <?php selected( $priority, '' ); ?>>
<?php esc_html_e( 'Default', 'xml-sitemap-generator-for-google' ); ?>
</option>
<?php for ( $i = 0; $i <= 10; $i++ ) :
$label = number_format( $i / 10, 1 );
?>
<option value="<?php echo esc_attr( $i ); ?>" <?php selected( (string) $priority, (string) $i ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endfor; ?>
</select>
</td>
</tr>
<?php } ?>
<?php if ( ! apply_filters( 'xml_sitemap_disable_post_meta__sitemap_frequency', false ) ) { ?>
<tr>
<td>
<label for="_sitemap_frequency"><?php esc_html_e( 'Post Frequency', 'xml-sitemap-generator-for-google' ); ?></label>
</td>
<td>
<div class="grim-select grim-select-default"
data-name="_sitemap_frequency">
<div class="grim-select__trigger">
<span>
<?php echo esc_html( $frequency_options[ $frequency ] ?? __( 'Default', 'xml-sitemap-generator-for-google' ) ); ?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<?php foreach ( $frequency_options as $opt_value => $label ) : ?>
<div class="grim-option <?php echo (string) $frequency === (string) $opt_value ? 'selected' : ''; ?>"
data-value="<?php echo esc_attr( $opt_value ); ?>">
<?php echo esc_html( $label ); ?>
</div>
<?php endforeach; ?>
</div>
</div>
<select id="_sitemap_frequency"
name="_sitemap_frequency"
class="grim-hidden-select"
hidden>
<?php foreach ( $frequency_options as $opt_value => $label ) : ?>
<option value="<?php echo esc_attr( $opt_value ); ?>" <?php selected( (string) $frequency, (string) $opt_value ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endforeach; ?>
</select>
</td>
</tr>
<?php } ?>
</table>
<?php sgg_show_pro_overlay( array( 'utm' => 'meta-box' ) ); ?>
</div>

View File

@@ -0,0 +1,237 @@
<?php
/**
* @var $args
*/
use GRIM_SG\Dashboard;
use GRIM_SG\Cache;
use GRIM_SG\GoogleNews;
use GRIM_SG\ImageSitemap;
use GRIM_SG\VideoSitemap;
$settings = $args['settings'] ?? new stdClass();
?>
<div class="grim-section">
<div class="grim-toggle-section">
<strong>
<?php
Dashboard::render(
'fields/checkbox.php',
array(
'name' => 'enable_cache',
'value' => $settings->enable_cache ?? false,
'label' => esc_html__( 'Cache', 'xml-sitemap-generator-for-google' ),
'class' => 'has-dependency',
'data' => array( 'target' => 'sitemap-cache' ),
)
);
?>
</strong>
</div>
<div class="inside">
<p class="grim-section-desc grim-mb-20">
<?php esc_html_e( 'All below options will be available after enabling Sitemap Cache. Sitemaps Content will be cached for faster loading.', 'xml-sitemap-generator-for-google' ); ?>
</p>
<p class="cache-timeout-group grim-mb-20">
<?php
$cache_timeout_period = $settings->cache_timeout_period ?? 3600;
$args = array(
'label' => __( 'Cache Expiration Time:', 'xml-sitemap-generator-for-google' ),
'name' => 'cache_timeout_period',
'value' => (string) $cache_timeout_period,
'options' => array(
'60' => __( 'minute(s)', 'xml-sitemap-generator-for-google' ),
'3600' => __( 'hour(s)', 'xml-sitemap-generator-for-google' ),
'86400' => __( 'day(s)', 'xml-sitemap-generator-for-google' ),
),
'select_size' => 'grim-select-small',
);
?>
<div class="grim-select-label sitemap-cache" data-search-id="<?php echo esc_attr( $args['name'] ); ?>">
<?php echo esc_html( $args['label'] ); ?>
</div>
<div class="grim-cache-time grim-mb-20">
<input type="number" id="cache_timeout" name="cache_timeout" class="grim-input sitemap-cache" value="<?php echo esc_attr( $settings->cache_timeout ?? 24 ); ?>"/>
<div class="grim-select <?php echo esc_attr( $args['select_size'] ?? 'grim-select-default' ); ?> sitemap-cache" data-name="<?php echo esc_attr( $args['name'] ); ?>">
<div class="grim-select__trigger">
<span>
<?php echo esc_html( $args['options'][ $args['value'] ] ?? __( 'None', 'xml-sitemap-generator-for-google' ) ); ?>
</span>
<i class="grim-icon-chevron-down"></i>
</div>
<div class="grim-options">
<?php foreach ( $args['options'] as $value => $label ) { ?>
<div class="grim-option <?php echo $args['options'][ $args['value'] ] === $label ? 'selected' : ''; ?>" data-value="<?php echo esc_attr( $value ); ?>">
<?php echo esc_html( $label ); ?>
</div>
<?php } ?>
</div>
</div>
<select id="<?php echo esc_attr( $args['name'] ); ?>" name="<?php echo esc_attr( $args['name'] ); ?>" class="grim-hidden-select" hidden>
<?php foreach ( $args['options'] as $value => $label ) { ?>
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, $args['value'] ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php } ?>
</select>
</div>
</p>
<div class="sitemap-cache">
<table class="grim-table grim-table-small-row wp-list-table widefat fixed striped" role="presentation">
<thead>
<tr>
<th><span data-search-id="last_cached_time"><?php esc_html_e( 'Last Cached Time:', 'xml-sitemap-generator-for-google' ); ?></span></th>
</tr>
</thead>
<tbody>
<?php if ( $settings->enable_sitemap ) { ?>
<tr>
<td>
<span><?php esc_html_e( 'XML Sitemap', 'xml-sitemap-generator-for-google' ); ?></span>:
</td>
<td class="grim-td-center"><i><?php echo esc_html( Cache::get_time_formatted( 'sitemap' ) ); ?></i></td>
<td>
<a href="<?php echo esc_url( sgg_get_sitemap_url( $settings->sitemap_url, 'sitemap_xml' ) ); ?>" target="_blank" class="grim-button white">
<span><?php esc_html_e( 'View', 'xml-sitemap-generator-for-google' ); ?></span>
</a>
</td>
</tr>
<?php } ?>
<?php if ( sgg_pro_enabled() && $settings->enable_html_sitemap ) { ?>
<tr>
<td>
<span><?php esc_html_e( 'HTML Sitemap', 'xml-sitemap-generator-for-google' ); ?></span>:
</td>
<td class="grim-td-center"><i><?php echo esc_html( Cache::get_time_formatted( 'sitemap' ) ); ?></i></td>
<td>
<a href="<?php echo esc_url( sgg_get_sitemap_url( $settings->html_sitemap_url, 'sitemap_html' ) ); ?>" target="_blank" class="grim-button white">
<span><?php esc_html_e( 'View', 'xml-sitemap-generator-for-google' ); ?></span>
</a>
</td>
</tr>
<?php } ?>
<?php if ( $settings->enable_google_news ) { ?>
<tr>
<td>
<span><?php esc_html_e( 'Google News', 'xml-sitemap-generator-for-google' ); ?></span>:
</td>
<td class="grim-td-center"><i><?php echo esc_html( Cache::get_time_formatted( GoogleNews::$template ) ); ?></i></td>
<td>
<a href="<?php echo esc_url( sgg_get_sitemap_url( $settings->google_news_url, 'google_news' ) ); ?>" target="_blank" class="grim-button white">
<span><?php esc_html_e( 'View', 'xml-sitemap-generator-for-google' ); ?></span>
</a>
</td>
</tr>
<?php } ?>
<?php if ( $settings->enable_image_sitemap ) { ?>
<tr>
<td>
<span><?php esc_html_e( 'Image Sitemap', 'xml-sitemap-generator-for-google' ); ?></span>:
</td>
<td class="grim-td-center"><i><?php echo esc_html( Cache::get_time_formatted( ImageSitemap::$template ) ); ?></i></td>
<td>
<a href="<?php echo esc_url( sgg_get_sitemap_url( $settings->image_sitemap_url, 'image_sitemap' ) ); ?>" target="_blank" class="grim-button white">
<span><?php esc_html_e( 'View', 'xml-sitemap-generator-for-google' ); ?></span>
</a>
</td>
</tr>
<?php } ?>
<?php if ( $settings->enable_video_sitemap ) { ?>
<tr>
<td>
<span><?php esc_html_e( 'Video Sitemap', 'xml-sitemap-generator-for-google' ); ?></span>:
</td>
<td class="grim-td-center"><i><?php echo esc_html( Cache::get_time_formatted( VideoSitemap::$template ) ); ?></i></td>
<td>
<a href="<?php echo esc_url( sgg_get_sitemap_url( $settings->video_sitemap_url, 'video_sitemap' ) ); ?>" target="_blank" class="grim-button white">
<span><?php esc_html_e( 'View', 'xml-sitemap-generator-for-google' ); ?></span>
</a>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<div class="grim-notice grim-mb-20">
<i class="grim-icon-information"></i>
<p>
<?php
echo sprintf(
esc_html__( 'Note: %s', 'xml-sitemap-generator-for-google' ),
'<span>' . esc_html__( 'Sitemap Cache will only be created when someone opens/visits the Sitemap on front-end.', 'xml-sitemap-generator-for-google' ) . '</span>'
)
?>
</p>
</div>
</div>
<p class="sitemap-cache grim-button-section" data-search-id="clear_cache">
<input type="hidden" name="clear_cache" value="">
<button type="submit" id="clear-sitemap-cache" class="grim-button white sitemap-cache">
<span>
<i class="grim-icon-trash"></i>
<?php esc_html_e( 'Clear Cache', 'xml-sitemap-generator-for-google' ); ?>
</span>
</button>
</p>
</div>
</div>
<div class="grim-section <?php echo esc_attr( sgg_pro_class() ); ?>">
<?php sgg_show_pro_badge(); ?>
<div class="grim-toggle-section pro-wrapper <?php echo esc_attr( sgg_pro_class() ); ?>">
<p>
<?php
Dashboard::render(
'fields/checkbox.php',
array(
'name' => 'clear_cache_on_save_post',
'class' => 'sitemap-cache',
'value' => $settings->clear_cache_on_save_post ?? false,
'label' => esc_html__( 'Smart Caching', 'xml-sitemap-generator-for-google' ),
)
);
?>
</p>
<p class="grim-section-desc inside sitemap-cache"><?php esc_html_e( 'Clear cache when Page/Post created or updated', 'xml-sitemap-generator-for-google' ); ?></p>
</div>
<?php sgg_show_pro_overlay(); ?>
</div>
<div class="grim-section">
<div class="grim-toggle-section pro-wrapper <?php echo esc_attr( sgg_pro_class() ); ?>">
<p>
<?php
Dashboard::render(
'fields/checkbox.php',
array(
'name' => 'disable_media_sitemap_cache',
'value' => $settings->disable_media_sitemap_cache ?? false,
'label' => esc_html__( 'Disable Media Sitemap Cache Collection', 'xml-sitemap-generator-for-google' ),
)
);
?>
</p>
<p class="inside grim-section-desc">
<?php esc_html_e( 'If you are having issues with Image and Video Sitemaps, you can try to disable Media Sitemap Cache Collection.', 'xml-sitemap-generator-for-google' ); ?>
<br>
</p>
<div class="grim-notice">
<i class="grim-icon-information"></i>
<p>
<?php
echo sprintf(
esc_html__( 'Note: %s', 'xml-sitemap-generator-for-google' ),
'<span>' . esc_html__( 'This will affect the performance of Media Sitemap Generation.', 'xml-sitemap-generator-for-google' ) . '</span>'
)
?>
</p>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More