Initial commit.

This commit is contained in:
dcooperdalrymple
2024-09-06 16:21:20 -05:00
commit 9387d15c4b
15 changed files with 758 additions and 0 deletions

View File

@@ -0,0 +1,239 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreIssuu
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreIssuu;
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());
}
}

159
includes/class-settings.php Normal file
View File

@@ -0,0 +1,159 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreIssuu
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreIssuu;
if (!defined('ABSPATH')) exit;
class Settings {
use Singleton;
private const PARENT_SLUG = 'options-general.php';
private const CAPABILITY = 'manage_options';
private array $options;
public function __construct() {
add_action('admin_menu', [$this, 'admin_menu'], 20);
add_action('admin_init', [$this, 'register_settings']);
add_filter('plugin_action_links_' . plugin_basename(Plugin::instance()->get_file()), [$this, 'plugin_action_links'], 10, 1);
}
private function get_menu_slug():string {
return Plugin::instance()->get_id();
}
private function get_menu_title():string {
return Plugin::instance()->get_title();
}
private function get_page_title():string {
return sprintf(
Plugin::__('%s Settings'),
Plugin::instance()->get_title()
);
}
// Register settings page
public function admin_menu():void {
add_submenu_page(
self::PARENT_SLUG,
$this->get_page_title(),
$this->get_menu_title(),
self::CAPABILITY,
$this->get_menu_slug(),
[$this, 'render']
);
}
// Register settings fields
private function get_option_group():string {
return Plugin::instance()->get_id();
}
private function get_option_name():string {
return Plugin::instance()->get_id();
}
public function register_settings():void {
register_setting($this->get_option_group(), $this->get_option_name(), [
'type' => 'array',
'label' => $this->get_page_title(),
'sanitize_callback' => [$this, 'sanitize'],
'default' => [
'client_id' => '',
'client_secret' => '',
'token' => '',
],
]);
add_settings_section(
'api',
Plugin::__('API Settings'),
function () {
printf(
'<p>%s</p>',
Plugin::__('See <a href="https://help.issuu.com/hc/en-us/articles/23059561681563-Issuu-API-v2-Getting-Started">Issuu API documentation</a> to learn how to generate an API client with your Issuu account.')
);
},
$this->get_menu_slug()
);
add_settings_field(
'client_id',
Plugin::__('Client ID'),
[$this, 'the_field'],
$this->get_menu_slug(),
'api'
);
add_settings_field(
'client_secret',
Plugin::__('Client Secret'),
[$this, 'the_field'],
$this->get_menu_slug(),
'api'
);
add_settings_field(
'token',
Plugin::__('Token'),
[$this, 'the_field'],
$this->get_menu_slug(),
'api'
);
}
public function the_field(array $args):void {
printf(
'<input id="%s" name="%s[%s]" type="text" value="%s" />',
esc_attr($args['name']),
esc_attr($args['option_group']),
esc_attr($args['name']),
esc_attr($this->options[$args['name']] ?? '')
);
if (isset($args['description']) && !empty($args['description'])) {
printf('<p class="description">%s</p>', esc_html($args['description']));
}
}
// Output settings page
public function render():void {
$this->options = get_option($this->get_option_group());
echo '<div class="wrap">';
printf('<h1>%s</h1>', esc_html($this->get_page_title()));
echo '<form method="post" action="options.php">';
settings_fields($this->get_option_group());
do_settings_sections($this->get_menu_slug());
submit_button();
echo '</form>';
echo '</div>';
}
// 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;
}
public function get_url():string {
return add_query_arg(array_filter([
'page' => $this->get_menu_slug(),
]), admin_url(self::PARENT_SLUG));
}
}
Settings::instance();

2
includes/index.php Normal file
View File

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

View File

@@ -0,0 +1,27 @@
<?php
/**
* @package CleverOgre
* @subpackage OgreIssuu
* @version 0.1.0
* @since 0.1.0
*/
namespace OgreIssuu;
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];
}
}