Initial build.

This commit is contained in:
dcooperdalrymple
2024-06-06 13:07:22 -05:00
commit 544cc6aa9a
24 changed files with 3419 additions and 0 deletions

View File

@@ -0,0 +1,239 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema;
defined('ABSPATH') || exit;
abstract class PluginBase {
use Singleton;
const REQUIREMENT_NONE = 0x01;
const REQUIREMENT_PLUGIN = 0x02;
const REQUIREMENT_CLASS = 0x04;
protected string $file;
protected array $requirements;
protected array $files;
private array $plugin_data;
public function __construct(string $file = __FILE__) {
$this->file = $file;
$this->requirements = [];
$this->files = [];
$this->plugin_data = [];
// Load composer packages
$this->setup_composer();
// Setup Plugin Updates
$this->setup_updater();
// Set Text Domain
load_plugin_textdomain($this->get_textdomain(), false, plugin_basename(dirname($this->file)) . '/lang');
// Requirements Check
add_action('plugins_loaded', [$this, 'check_requirements'], 1, 0);
$this->enable();
}
// Plugin Initialization
protected function enable() {
add_action('plugins_loaded', [$this, 'load'], 10, 0);
add_filter('acf/settings/load_json', [$this, 'register_acf_json'], 10, 1);
}
protected function disable() {
remove_action('plugins_loaded', [$this, 'load'], 10, 0);
remove_filter('acf/settings/load_json', [$this, 'register_acf_json'], 10, 1);
}
public function load() {
$this->load_files();
}
public function register_acf_json(array $paths):array {
$path = $this->get_path() . 'acf-json';
if (!in_array($path, $paths)) $paths[] = $path;
return $paths;
}
// Setup
protected function setup_composer() {
require_once($this->get_path() . 'vendor/autoload.php');
}
protected function setup_updater() {
global $wppul_plugin_file, $wppul_server, $wppul_license_required;
$wppul_plugin_file = $this->get_file();
$wppul_server = 'https://plugins.cleverogre.com';
$wppul_license_required = false;
if (!class_exists('Puc_v4_Factory')) require_once($this->get_path() . 'lib/wp-package-updater-lib/plugin-update-checker/plugin-update-checker.php');
require_once($this->get_path() . 'lib/wp-package-updater-lib/package-updater.php');
}
// Requirements
protected function add_requirement(string $key, array $data) {
$this->requirements[$key] = wp_parse_args($data, [
'name' => '',
'url' => '',
'type' => self::REQUIREMENT_NONE,
'plugin' => '',
'class' => '',
]);
}
public function check_requirements() {
$invalid = false;
foreach ($this->requirements as $key => $data) {
if ($data['type'] & self::REQUIREMENT_NONE) continue;
if ($data['type'] & self::REQUIREMENT_PLUGIN && !empty($data['plugin']) && function_exists('is_plugin_active') && is_plugin_active($data['plugin'])) continue;
if ($data['type'] & self::REQUIREMENT_CLASS && !empty($data['class']) && class_exists($data['class'])) continue;
$this->add_requirement_notice($data);
$invalid = true;
}
if (!!$invalid) $this->disable();
}
protected function add_requirement_notice($data) {
add_action('admin_notices', function () use ($data) {
$message = sprintf(
__('In order to use the %1$s plugin, it is required that you install and activate the %3$s plugin. You can do this on the <a href="%2$s">plugins</a> page when logged in as an administrator. To download this plugin, visit the <a href="%4$s" target="_blank">%3$s website</a>.', $this->get_textdomain()),
$this->get_title(),
esc_url(admin_url('plugins.php')),
esc_html($data['name']),
esc_url($data['url'])
);
printf('<div class="%s"><p>%s</p></div>', esc_attr('notice notice-error'), wpautop(wp_kses_post($message)));
});
}
// Plugin Files
protected function add_file(string $relpath):bool {
if (!is_string($relpath) || empty($relpath)) return false;
$this->files[] = $relpath;
return true;
}
protected function add_files(array $relpaths):bool {
$valid = true;
foreach ($relpaths as $relpath) {
if (!$this->add_file($relpath)) $valid = false;
}
return $valid;
}
protected function load_files():bool {
if (empty($this->files)) return false;
$valid = true;
foreach ($this->files as $relpath) {
$path = rtrim($this->get_path(), '/') . '/' . ltrim($relpath, '/');
if (!file_exists($path)) $valid = false;
else include_once($path);
}
return $valid;
}
// Plugin Data Accessors
private function get_data(string $key):string {
if (!function_exists('get_plugin_data')) require_once(ABSPATH . 'wp-admin/includes/plugin.php');
if (!is_array($this->plugin_data) || empty($this->plugin_data)) {
$this->plugin_data = get_plugin_data($this->file);
}
if (!array_key_exists($key, $this->plugin_data)) return '';
return $this->plugin_data[$key];
}
public function get_textdomain():string {
return $this->get_data('TextDomain');
}
public function get_id():string {
return $this->get_textdomain();
}
public function get_version():string {
return $this->get_data('Version');
}
public function get_title():string {
return __($this->get_data('Name'), $this->get_textdomain());
}
public function get_description():string {
return __($this->get_data('Description'), $this->get_textdomain());
}
// Plugin File Path Calculations
public function get_file():string {
return $this->file;
}
public function get_path(string $file = ''):string {
if (empty($file)) $file = $this->file;
return trailingslashit(dirname($file));
}
public function get_dir(string $file = ''):string {
$dir = $this->get_path($file);
$count = 0;
// Sanitize for Win32 installs
$dir = str_replace('\\', '/', $dir);
// If file is in plugins folder
$wp_plugin_dir = str_replace('\\', '/', WP_PLUGIN_DIR);
$dir = str_replace($wp_plugin_dir, plugins_url(), $dir, $count);
if ($count < 1) {
// If file is in wp-content folder
$wp_content_dir = str_replace('\\', '/', WP_CONTENT_DIR);
$dir = str_replace($wp_content_dir, content_url(), $dir, $count);
}
if ($count < 1) {
// If file is in ??? folder
$wp_dir = str_replace('\\', '/', ABSPATH);
$dir = str_replace($wp_dir, site_url('/'), $dir);
}
return $dir;
}
public function get_hook(string $file = ''):string {
if (empty($file)) $file = $this->file;
return basename(dirname($file)) . '/' . basename($file);
}
public function get_url(string $file = ''):string {
if (empty($file)) $file = $this->file;
return plugin_dir_url($file);
}
// Static Translation Functions
public static function __(string $text):string {
return __($text, self::instance()->get_textdomain());
}
public static function esc_html__(string $text):string {
return esc_html__($text, self::instance()->get_textdomain());
}
public static function esc_attr__(string $text):string {
return esc_attr__($text, self::instance()->get_textdomain());
}
}

261
includes/class-data.php Normal file
View File

@@ -0,0 +1,261 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema;
if (!defined('ABSPATH')) exit;
class Data {
public const SCHEMA_TYPES = ['business', 'person', 'product', 'event', 'organization', 'website', 'custom'];
public static function get_schema():array {
if (Settings::has_post_types() && is_singular(Settings::get_post_types())) {
$schema_object = self::get_schema_object(get_the_ID());
if (!empty($schema_object)) return $schema_object;
}
return self::get_schema_object();
}
public static function has_schema():bool {
return !empty(self::get_schema());
}
public static function get_schema_object(string|int $id = 'option'):array {
$cache_key = sprintf('ogreschema/get_schema_object_%s', strval($id));
if (is_array($cache = wp_cache_get($cache_key))) return $cache;
$schema_type = get_field('schema_type', $id);
if (!in_array($schema_type, self::SCHEMA_TYPES)) return [];
$acf_object = get_field('schema_' . $schema_type, $id);
$schema_object = array();
switch ($schema_type) {
case 'business':
case 'organization':
if (isset($acf_object['type']) && !empty($acf_object['type']) && strtolower($acf_object['type']) != 'none') {
$schema_object['@type'] = $acf_object['type']; // type field with capitals but without spaces
} else if ($schema_type == 'business') {
$schema_object['@type'] = 'LocalBusiness';
} else if ($schema_type == 'organization') {
$schema_object['@type'] = 'Organization';
} else {
return [];
}
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
if (isset($acf_object['urls']) && !empty($acf_object['urls']) && is_array($acf_object['urls'])) {
$schema_object['sameAs'] = array();
foreach ($acf_object['urls'] as $row) {
$schema_object['sameAs'][] = $row['url'];
}
}
if (isset($acf_object['logo']) && !empty($acf_object['logo']) && isset($acf_object['logo']['url']) && !empty($acf_object['logo']['url'])) $schema_object['logo'] = $acf_object['logo']['url'];
if (isset($acf_object['image']) && !empty($acf_object['image']) && isset($acf_object['image']['url']) && !empty($acf_object['image']['url'])) $schema_object['image'] = $acf_object['image']['url'];
if (isset($acf_object['description']) && !empty($acf_object['description'])) $schema_object['description'] = $acf_object['description'];
if (isset($acf_object['address']) || isset($acf_object['city']) || isset($acf_object['state']) || isset($acf_object['postal_code']) || isset($acf_object['country'])) {
$schema_object['address'] = array('@type' => 'PostalAddress');
if (isset($acf_object['address']) && !empty($acf_object['address'])) $schema_object['address']['streetAddress'] = $acf_object['address'];
if (isset($acf_object['po_box']) && !empty($acf_object['po_box'])) $schema_object['address']['postOfficeBoxNumber'] = $acf_object['po_box'];
if (isset($acf_object['city']) && !empty($acf_object['city'])) $schema_object['address']['addressLocality'] = $acf_object['city'];
if (isset($acf_object['state']) && !empty($acf_object['state'])) $schema_object['address']['addressRegion'] = $acf_object['state'];
if (isset($acf_object['postal_code']) && !empty($acf_object['postal_code'])) $schema_object['address']['postalCode'] = $acf_object['postal_code'];
if (isset($acf_object['country']) && !empty($acf_object['country'])) $schema_object['address']['addressCountry'] = $acf_object['country'];
}
if (isset($acf_object['location']) && is_array($acf_object['location']) && !empty($acf_object['location'])) {
$schema_object['geo'] = array(
'@type' => 'GeoCoordinates',
'latitude' => $acf_object['location']['lat'],
'longitude' => $acf_object['location']['lng'],
);
$schema_object['hasMap'] = 'https://www.google.com/maps/place/' . urlencode($acf_object['location']['address']);
}
if (isset($acf_object['hours']) && !empty($acf_object['hours']) && is_array($acf_object['hours'])) {
$schema_object['openingHours'] = self::build_hours($acf_object['hours']);
}
if (isset($acf_object['price']) && is_numeric($acf_object['price']) && intval($acf_object['price']) >= 1 && intval($acf_object['price']) <= 5) {
$schema_object['priceRange'] = str_repeat('$', intval($acf_object['price']));
}
if (isset($acf_object['phone']) && !empty($acf_object['phone'])) {
$contact = array(
'@type' => 'ContactPoint',
'telephone' => $acf_object['phone'],
);
if (isset($acf_object['contact_type']) && !empty($acf_object['contact_type']) && strtolower($acf_object['contact_type']) != 'none') $contact['contactType'] = $acf_object['contact_type'];
if (isset($acf_object['contact_option']) && !empty($acf_object['contact_option']) && strtolower($acf_object['contact_option']) != 'none') $contact['contactOption'] = $acf_object['contact_option'];
$schema_object['contactPoint'] = $contact;
$schema_object['telephone'] = $acf_object['phone'];
}
break;
case 'person':
$schema_object['@type'] = 'person';
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
if (isset($acf_object['job_title']) && !empty($acf_object['job_title'])) $schema_object['jobTitle'] = $acf_object['job_title'];
if (isset($acf_object['address']) || isset($acf_object['po_box']) || isset($acf_object['city']) || isset($acf_object['state']) || isset($acf_object['postal_code']) || isset($acf_object['country'])) {
$schema_object['address'] = array('@type' => 'PostalAddress');
if (isset($acf_object['address']) && !empty($acf_object['address'])) $schema_object['address']['streetAddress'] = $acf_object['address'];
if (isset($acf_object['po_box']) && !empty($acf_object['po_box'])) $schema_object['address']['postOfficeBoxNumber'] = $acf_object['po_box'];
if (isset($acf_object['city']) && !empty($acf_object['city'])) $schema_object['address']['addressLocality'] = $acf_object['city'];
if (isset($acf_object['state']) && !empty($acf_object['state'])) $schema_object['address']['addressRegion'] = $acf_object['state'];
if (isset($acf_object['postal_code']) && !empty($acf_object['postal_code'])) $schema_object['address']['postalCode'] = $acf_object['postal_code'];
if (isset($acf_object['country']) && !empty($acf_object['country'])) $schema_object['address']['addressCountry'] = $acf_object['country'];
}
if (isset($acf_object['email']) && !empty($acf_object['email']) && is_email($acf_object['email'])) $schema_object['email'] = $acf_object['email'];
if (isset($acf_object['phone']) && !empty($acf_object['phone'])) $schema_object['telephone'] = $acf_object['phone'];
if (isset($acf_object['birth_date']) && !empty($acf_object['birth_date'])) $schema_object['birthDate'] = $acf_object['birth_date'];
break;
case 'product':
$schema_object['@type'] = 'product';
if (isset($acf_object['brand']) && !empty($acf_object['brand'])) $schema_object['brand'] = $acf_object['brand'];
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
if (isset($acf_object['description']) && !empty($acf_object['description'])) $schema_object['description'] = $acf_object['description'];
if (isset($acf_object['image']) && !empty($acf_object['image']) && isset($acf_object['image']['url']) && !empty($acf_object['image']['url'])) $schema_object['image'] = $acf_object['image']['url'];
if (isset($acf_object['rating_value']) && !empty($acf_object['rating_value'])) {
$schema_object['aggregateRating'] = array(
'@type' => 'aggregateRating',
'ratingValue' => $acf_object['rating_value'],
);
if (isset($acf_object['review_count']) && $acf_object['review_count'] > 0) $schema_object['aggregateRating']['reviewCount'] = $acf_object['review_count'];
}
break;
case 'event':
if (isset($acf_object['type']) && !empty($acf_object['type']) && strtolower($acf_object['type']) != 'none') {
$schema_object['@type'] = $acf_object['type']; // type field with capitals but without spaces
} else {
$schema_object['@type'] = 'Event';
}
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
if (isset($acf_object['description']) && !empty($acf_object['description'])) $schema_object['description'] = $acf_object['description'];
if (isset($acf_object['date_start']) && !empty($acf_object['date_start'])) $schema_object['startDate'] = $acf_object['date_start'];
if (isset($acf_object['date_end']) && !empty($acf_object['date_end'])) $schema_object['endDate'] = $acf_object['date_end'];
if (isset($acf_object['venue_name']) || isset($acf_object['address'])) {
$location = array('@type' => 'Place');
if (isset($acf_object['venue_name']) && !empty($acf_object['venue_name'])) $location['name'] = $acf_object['venue_name'];
if (isset($acf_object['venue_url']) && !empty($acf_object['venue_url'])) $location['sameAs'] = $acf_object['venue_url'];
if (isset($acf_object['address']) && !empty($acf_object['address'])) {
$location['address'] = array(
'@type' => 'PostalAddress',
'streetAddress' => $acf_object['address'],
);
if (isset($acf_object['city']) && !empty($acf_object['city'])) $location['address']['addressLocality'] = $acf_object['city'];
if (isset($acf_object['state']) && !empty($acf_object['state'])) $location['address']['addressRegion'] = $acf_object['state'];
if (isset($acf_object['postal_code']) && !empty($acf_object['postal_code'])) $location['address']['postalCode'] = $acf_object['postal_code'];
if (isset($acf_object['country']) && !empty($acf_object['country'])) $location['address']['addressCountry'] = $acf_object['country'];
}
if (count($location) > 1) $schema_object['location'] = $location;
}
if (isset($acf_object['offer_description']) || isset($acf_object['offer_url']) || isset($acf_object['offer_price'])) {
$offer = array('@type' => 'Offer');
if (isset($acf_object['offer_description']) && !empty($acf_object['offer_description'])) $offer['description'] = $acf_object['offer_description'];
if (isset($acf_object['offer_url']) && !empty($acf_object['offer_url'])) $offer['url'] = $acf_object['offer_url'];
if (isset($acf_object['offer_price']) && !empty($acf_object['offer_price'])) $offer['price'] = $acf_object['offer_price'];
if (count($offer) > 1) $schema_object['offer'] = $offer;
}
break;
case 'website':
$schema_object['@type'] = 'WebSite';
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
if (isset($acf_object['name_alternate']) && !empty($acf_object['name_alternate'])) $schema_object['alternateName'] = $acf_object['name_alternate'];
break;
case 'custom':
if (isset($acf_object['fields']) && !empty($acf_object['fields'])) {
foreach ($acf_object['fields'] as $field) {
if (!isset($field['key']) || empty($field['key'])) continue;
switch ($field['type']) {
case 'array':
$schema_object[$field['key']] = array();
foreach ($field['array'] as $array_item) {
if (!isset($array_item['value']) || empty($array_item['value'])) continue;
$schema_object[$field['key']][] = $array_item['value'];
}
break;
case 'object':
$schema_object[$field['key']] = array();
foreach ($field['object'] as $object_item) {
if (!isset($object_item['key']) || empty($object_item['key'])) continue;
$schema_object[$field['key']][$object_item['key']] = $object_item['value'];
}
break;
default:
$schema_object[$field['key']] = $field['value'];
break;
}
}
}
break;
}
if (empty($schema_object)) return [];
// Global Settings
if (!isset($schema_object['url'])) $schema_object['url'] = get_site_url();
if (!isset($schema_object['@context'])) $schema_object['@context'] = 'http://www.schema.org';
$schema_object = apply_filters('ogreschema/get_schema_object', $schema_object, $id);
// Set Cache
wp_cache_set($cache_key, $schema_object, 'ogre_schema');
return $schema_object;
}
private static function build_hours($hours_object) {
$hours = '';
foreach ($hours_object as $row) {
if (!isset($row['day']) || empty($row['day'])) continue;
if ($hours != '') $hours .= ', ';
$hours .= $row['day'];
if (isset($row['open']) && isset($row['close']) && !empty($row['open']) && !empty($row['close'])) {
$hours .= ' ' . $row['open'] . '-' . $row['close'];
}
}
return $hours;
}
}

60
includes/class-fields.php Normal file
View File

@@ -0,0 +1,60 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema;
if (!defined('ABSPATH')) exit;
class Fields {
use Singleton;
public function __construct() {
add_filter('acf/get_field_group', [$this, 'assign_post_type_locations'], 10, 1);
add_filter('acf/load_field/key=field_5c62eb9db90a6', [$this, 'load_post_types'], 10, 1);
add_filter('acf/load_field/key=field_5a05e86e18797', [$this, 'load_business_types'], 10, 1);
add_filter('acf/load_field/key=field_5a09f1e06f181', [$this, 'load_organization_types'], 10, 1);
}
public function assign_post_type_locations(array $group):array {
if ($group['key'] !== 'group_5a05f48ad5e1a' || !Settings::has_post_types()) return $group;
foreach (Settings::get_post_types() as $post_type) {
if (is_null(get_post_type_object($post_type))) continue;
$group['location'][] = [[
'param' => 'post_type',
'operator' => '==',
'value' => $post_type,
]];
}
return $group;
}
public function load_post_types(array $field):array {
$field['choices'] = wp_list_pluck(get_post_types(['public' => true], 'objects'), 'label', 'name');
return $field;
}
public function load_business_types(array $field):array {
$field['choices'] = $this->get_json_data('data/business-type.json');
return $field;
}
public function load_organization_types(array $field):array {
$field['choices'] = $this->get_json_data('data/organization-type.json');
return $field;
}
private function get_json_data(string $relpath):array {
$path = Plugin::instance()->get_path() . ltrim($relpath, '/');
if (!str_ends_with($path, '.json') || !file_exists($path)) return [];
$data = json_decode(file_get_contents($path), true);
return is_array($data) ? $data : [];
}
}
Fields::instance();

31
includes/class-output.php Normal file
View File

@@ -0,0 +1,31 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema;
if (!defined('ABSPATH')) exit;
class Output {
use Singleton;
public function __construct() {
add_action('wp_footer', [$this, 'render']);
}
// Add JSON to Footer
public function render() {
if (!Data::has_schema()) return;
printf(
'<script type="application/ld+json">%s</script>',
json_encode(Data::get_schema()) // NOTE: esc_js()?
);
}
}
Output::instance();

View File

@@ -0,0 +1,72 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema;
if (!defined('ABSPATH')) exit;
class Settings {
use Singleton;
private const PARENT_SLUG = 'options-general.php';
private array $page = [];
public function __construct() {
add_action('admin_menu', [$this, 'admin_menu'], 20);
add_filter('plugin_action_links_' . plugin_basename(Plugin::instance()->get_file()), [$this, 'plugin_action_links'], 10, 1);
}
// Add Schema Page to Theme Options
public function admin_menu():void {
if (!function_exists('acf_add_options_sub_page')) return;
$this->page = acf_add_options_sub_page([
'page_title' => Plugin::__('Schema Metadata'),
'menu_title' => Plugin::__('Schema'),
'parent_slug' => self::PARENT_SLUG,
'menu_slug' => Plugin::instance()->get_id(),
'update_button' => Plugin::__('Save'),
'updated_message' => Plugin::__('Schema Updated'),
]);
}
// Add plugin link
public function plugin_action_links(array $links):array {
array_unshift($links, sprintf(
'<a href="%s">%s</a>',
esc_url($this->get_url()),
Plugin::esc_html__('Settings')
));
return $links;
}
private function get_menu_slug():string {
if (empty($this->page) || !isset($this->page['menu_slug'])) return '';
return (string)$this->page['menu_slug'];
}
public function get_url():string {
return add_query_arg(array_filter([
'page' => $this->get_menu_slug(),
]), admin_url(self::PARENT_SLUG));
}
// Settings Accessors
public static function get_post_types():array {
if (get_field('schema_setting_post_enable', 'option') !== true) return [];
return is_array($post_types = get_field('schema_setting_post_type', 'option')) ? $post_types : [];
}
public static function has_post_types():bool {
return !empty(self::get_post_types());
}
}
Settings::instance();

2
includes/index.php Normal file
View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden

View File

@@ -0,0 +1,60 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema\Integration;
if (!defined('ABSPATH')) exit;
use OgreSchema\Singleton;
use OgreSchema\Data;
class YoastSEO {
use Singleton;
public function __construct() {
add_filter('wpseo_json_ld_output', [$this, 'disable_wpseo'], 10, 2);
add_filter('ogreschema/get_schema_object', [$this, 'append_schema_data'], 10, 2);
}
// Disable Yoast JSON Output
public function disable_wpseo($data, $context) {
return !Data::has_schema() ? $data : false;
}
// Append unset data from Yoast
public function append_schema_data(array $schema_object, string|int $id):array {
$wpseo_schema = $this->get_wpseo_schema();
if (empty($wpseo_schema)) return $schema_object;
foreach ($wpseo_schema as $key => $value) {
if (isset($schema_object[$key]) && !empty($schema_object[$key])) continue;
$schema_object[$key] = $value;
}
return $schema_object;
}
// Override filter and get Yoast JSON data
private function get_wpseo_schema():array {
remove_filter('wpseo_json_ld_output', [$this, 'disable_wpseo'], 10, 2);
ob_start();
do_action('wpseo_json_ld');
$html = ob_get_clean();
add_filter('wpseo_json_ld_output', [$this, 'disable_wpseo'], 10, 2);
if (empty($html) || !preg_match_all('/<script[^>]*>(.+)<\/script>/m', $html, $matches)) return [];
$data = [];
foreach ($matches[1] as $json_str) {
$json_data = json_decode($json_str, true);
if (!is_null($json_data) && is_array($json_data)) $data = array_merge($data, $json_data);
}
return $data;
}
}
YoastSEO::instance();

View File

@@ -0,0 +1,2 @@
<?php
// Silence is golden

View File

@@ -0,0 +1,27 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreSchema
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreSchema;
defined('ABSPATH') || exit;
trait Singleton {
private static $instances = [];
private static $instance_classes = [];
final public static function instance() {
$class = get_called_class();
if (in_array($class, self::$instance_classes)) return self::$instances[array_search($class, self::$instance_classes)];
self::$instances[] = new $class();
self::$instance_classes[] = $class;
return self::$instances[count(self::$instances) - 1];
}
}