Файловый менеджер - Редактировать - /home/tuudkjt/globeasy/wp-includes/ID3/core.tar
Назад
composer.json 0000777 00000001503 15251357345 0007306 0 ustar 00 { "name": "wpdrill\/core", "description": "A toolset for WPDrill", "type": "library", "license": "MIT", "keywords": [ "wordpress", "plugin", "framework" ], "autoload": { "psr-4": { "Rvx\\WPDrill\\": "src\/" } }, "authors": [ { "name": "Nahid Bin Azhar", "email": "nahid.dns@gmail.com" } ], "minimum-stability": "dev", "require": { "php": ">=7.4 <8.6", "psr\/container": "^1.0", "php-di\/php-di": "^6.4", "twig\/twig": "^3.0 <3.8", "hassankhan\/config": "^3.1", "usmanhalalit\/viocon": "1.0.*@dev", "nyholm\/psr7": "^1.8", "nyholm\/psr7-server": "^1.1", "symfony\/console": "^5.4", "symfony\/process": "^5.4" } } src/Models/Model.php 0000777 00000003455 15251357345 0010357 0 ustar 00 <?php namespace Rvx\WPDrill\Models; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; use Rvx\WPDrill\Facade; /** * @method static self select(string ...$columns) * @method static array|object|null get() * @method static \stdClass|null first() * @method static \stdClass|null findAll(string $fieldName, $value) * @method static \stdClass|null find($value, $fieldName = 'id') * @method static int count() * @method static array|string insert(array $data) * @method static array|string update(array $data) * @method static array|string updateOrInsert(array $data) * @method static mixed delete() * @method static self where(string $key, $operator = null, $value = null) * @method static self orWhere(string $key, $operator = null, $value = null) * @method static self whereIn(string $key, array $values) * @method static self whereNull(string $key) * @method static QueryBuilderHandler transaction( \Closure $callback ) * @method static void chunk( int $count, callable $callback ); */ abstract class Model extends Facade { /** * @var string */ protected static $table; /** * @var string */ protected $primaryKey = 'id'; public static function getTableName() : string { return static::$table; } public static function getFacadeAccessor() { return QueryBuilderHandler::class; } /** * @param $method * @param $args * @return mixed */ public static function __callStatic($method, $args) { $instance = static::resolveFacadeInstance(static::getFacadeAccessor()); if (!$instance) { throw new \RuntimeException('A facade root has not been set.'); } $instance = $instance->table(self::getTableName()); return \call_user_func_array([$instance, $method], $args); } } src/Models/PostType.php 0000777 00000000647 15251357345 0011106 0 ustar 00 <?php namespace Rvx\WPDrill\Models; class PostType extends Model { protected static $table = 'posts'; public static ?string $postType = null; public static function __callStatic($method, $args) { $instance = parent::__callStatic($method, $args); if (self::$postType === null) { return $instance; } return $instance->where('post_type', self::$postType); } } src/Commands/PluginInfoCommand.php 0000777 00000001771 15251357345 0013205 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Helper\Table; use Rvx\Symfony\Component\Console\Helper\TableSeparator; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\DB\Migration\Migrator; use Rvx\WPDrill\Facades\Config; class PluginInfoCommand extends BaseCommand { protected function configure() { $this->setName('plugin:info')->setDescription('Display the plugin information')->setHelp('This command allows you to display the plugin information.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $config = Config::get('plugin'); $table = new Table($output); $table->setRows([['<comment>Name</comment>', $config['name']], new TableSeparator(), ['<comment>Version</comment>', $config['version']]]); $table->render(); return Command::SUCCESS; } } src/Commands/PluginSetupCommand.php 0000777 00000007425 15251357345 0013414 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Helper\Table; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; class PluginSetupCommand extends BaseCommand { protected function configure() { $this->setName('plugin:init')->setDescription('Setup the plugin')->setHelp('This command allows you to setup the plugin for development.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $pluginName = $this->ask('Enter the plugin name: '); $pluginSlug = $this->ask('Enter the plugin slug: '); $prefix = $this->ask('Enter the plugin prefix[space,hyphen will be converted to _]: '); $prefix = \str_replace([' ', '-'], ['_', '_'], $prefix); $functionPrefix = \lcfirst($prefix); $constPrefix = \strtoupper($prefix); $restNamespace = $this->ask('Enter the REST API namespace[space,hyphen will be converted to _]: '); $restNamespace = \str_replace([' ', '-'], ['_', '_'], $restNamespace); $rootNamespace = $this->ask('Enter the app root namespace: '); $appRootNamespace = \rtrim(\str_replace(' ', '', $rootNamespace), '\\'); $replaces = ['#[plugin-name]' => $pluginName, '#[plugin-slug]' => $pluginSlug, '#[plugin-prefix]' => $prefix, '#[const-prefix]' => $constPrefix, '#[function-prefix]' => $functionPrefix, '#[rest-namespace]' => $restNamespace, '#[root-namespace]' => $rootNamespace, 'namespace App' => 'namespace ' . $appRootNamespace, 'use App' => 'use ' . $appRootNamespace, '\\App\\' => '\\' . $appRootNamespace . '\\', '"App\\\\":' => '"' . $appRootNamespace . '\\\\":']; \copy(__DIR__ . '/../../stubs/wpdrill.stub', WPDRILL_ROOT_PATH . '/' . $pluginSlug . '.php'); \copy(__DIR__ . '/../../stubs/helpers.stub', WPDRILL_ROOT_PATH . '/app/Utilities/helpers.php'); if (\file_exists(WPDRILL_ROOT_PATH . '/wpdrill.php')) { \rename(WPDRILL_ROOT_PATH . '/wpdrill.php', WPDRILL_ROOT_PATH . '/' . \strtolower($pluginSlug) . '.php'); } $this->replaceExecute($replaces); $this->process(['composer', 'dump-autoload']); //$this->process(['composer', 'bin', 'php-scoper', 'require', '--dev', 'humbug/php-scoper']); $output->writeln('<info>Congratulations! Your plugin is ready to develop.</info>'); $table = new Table($output); $table->setHeaderTitle("Info"); $table->addRows([['<comment>Plugin Name</comment>', $pluginName], ['<comment>Plugin Slug</comment>', $pluginSlug], ['<comment>Plugin Prefix</comment>', $prefix], ['<comment>REST API Namespace</comment>', $restNamespace], ['<comment>Root Namespace</comment>', $rootNamespace]]); $table->render(); return Command::SUCCESS; } protected function replaceExecute(array $replaces) { $directory = WPDRILL_ROOT_PATH; // Text to search for $search = \array_keys($replaces); // Text to replace with $replace = \array_values($replaces); $this->replace($directory, $search, $replace); } protected function replace(string $directory, array $search, array $replace) { $files = \glob($directory . '/*'); foreach ($files as $file) { if (\is_file($file)) { $contents = \file_get_contents($file); $modified_contents = \str_replace($search, $replace, $contents); \file_put_contents($file, $modified_contents); } if (\is_dir($file)) { if (\basename($file) === 'vendor' || \basename($file) === 'pkgs') { continue; } $this->replace($file, $search, $replace); } } } } src/Commands/BaseCommand.php 0000777 00000003167 15251357345 0012006 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\Symfony\Component\Console\Question\Question; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Input\ArgvInput; use Rvx\Symfony\Component\Console\Output\BufferedOutput; use Rvx\Symfony\Component\Process\Process; class BaseCommand extends Command { protected InputInterface $input; protected OutputInterface $output; protected function initialize(InputInterface $input, OutputInterface $output) { $this->input = $input; $this->output = $output; } protected function ask(string $question, string $default = 'wpdrill') : string { $helper = $this->getHelper('question'); $question = new Question($question, $default); return $helper->ask($this->input, $this->output, $question); } protected function info(string $message) { $this->output->writeln('<info>' . $message . '</info>'); } protected function error(string $message) { $this->output->writeln('<error>' . $message . '</error>'); } protected function comment(string $message) { $this->output->writeln('<comment>' . $message . '</comment>'); } protected function process(array $command = []) : Process { if (empty($command)) { return new Process([]); } $helper = $this->getHelper('process'); $process = new Process($command); $process->setTimeout(360); return $helper->run($this->output, $process); } } src/Commands/PluginBuildCommand.php 0000777 00000016437 15251357345 0013356 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use DateTime; use DateTimeZone; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Input\InputOption; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\Symfony\Component\Console\Style\SymfonyStyle; use Rvx\WPDrill\Facades\Config; class PluginBuildCommand extends BaseCommand { protected function configure() { $this->setName('plugin:build')->addOption('prod', 'p', null, 'Build the plugin for production, this build remove dev dependencies')->addOption('set-version', 'x', InputOption::VALUE_REQUIRED, 'Added version to the newly build')->addOption('archive', 'a', InputOption::VALUE_REQUIRED, 'Archive the build. Supported formats: zip, tar')->setDescription('Build the plugin for production')->setHelp('This build command allow you to build the plugin for production.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $start = \time(); $io = new SymfonyStyle($input, $output); $version = ''; $date = new DateTime("now", new DateTimeZone("UTC")); $buildName = 'build-' . $date->format("Y-m-d\\THis\\Z"); if ($input->getOption('prod')) { $buildName .= '-prod'; } if ($input->getOption('set-version')) { $version = $input->getOption('set-version'); $buildName .= '-' . $version; } $outputDir = WPDRILL_ROOT_PATH . '/' . Config::get('plugin.build.output_dir', '.dist'); $buildDir = $outputDir . '/' . $buildName; $io->newLine(); $output->writeln('Building the plugin...'); if ($input->getOption('prod')) { $this->process(['composer', 'install', '--no-dev']); } $this->process(['./wpdrill', 'view:cache']); $this->executeCommandsBefore(WPDRILL_ROOT_PATH); if (!\file_exists(WPDRILL_ROOT_PATH . '/php-scoper')) { $output->writeln(['<error>No php-scoper executable file available</error>']); return Command::FAILURE; } $buildProcess = $this->process(['./php-scoper', 'add-prefix', '--force', '--output-dir=' . $buildDir]); if (!$buildProcess->isSuccessful()) { $output->writeln('<error>' . $buildProcess->getErrorOutput() . '</error>'); return Command::FAILURE; } if ($version !== '') { $io->newLine(); $this->updateBuildVersion($version, $buildDir); } $this->executeCommandsAfter($buildDir); if ($input->getOption('prod')) { $this->process(['composer', 'install', '--dev']); $io->newLine(); $this->cleanup($buildDir); } if ($archive = $input->getOption('archive')) { $io->newLine(); $this->archive($outputDir, $buildName, $archive); } $end = \time(); $totalTime = $end - $start; $io->newLine(); $output->writeln('<info>Plugin build successfully completed!</info>'); $io->newLine(); $output->writeln(['<comment>Build Name: ' . $buildName . '</comment>', '<comment>Time: ' . $totalTime . ' Seconds</comment>']); return Command::SUCCESS; } protected function executeCommandsBefore(string $buildDir) { $commands = Config::get('plugin.build.commands.before', []); $this->executeCommands($commands, $buildDir); } protected function executeCommandsAfter(string $buildDir) { $commands = Config::get('plugin.build.commands.after', []); $this->executeCommands($commands, $buildDir); } protected function executeCommands(array $commands, string $dir) { $this->output->writeln('<comment>Executing commands: </comment>'); foreach ($commands as $command) { $cmd = ['bash', '-c', 'cd ' . $dir . ' && ' . \implode(' ', $command)]; $this->output->writeln(' > ' . \implode(' ', $command) . ' ...'); try { $process = $this->process($cmd); if ($process->isSuccessful()) { $this->output->writeln('<info> > ' . \implode(' ', $command) . ' [DONE]</info>'); } else { $this->output->writeln('<error> >' . \implode(' ', $command) . ' [FAILED]</error>'); } } catch (\Exception $e) { $this->output->writeln('<error>' . $e->getMessage() . '</error>'); } \sleep(1); } } protected function cleanup(string $buildDir) { $files = Config::get('plugin.build.cleanup', []); $this->output->writeln('<comment>Cleaning: </comment>'); foreach ($files as $file) { try { if ($file === '/') { throw new \Exception('You can not delete root directory'); } if (\str_starts_with($file, '/')) { throw new \Exception('You can not delete system files'); } if (\is_dir($buildDir . '/' . $file)) { $cmd = ['bash', '-c', 'cd ' . $buildDir . ' && rm -rf ./' . $file]; } else { $cmd = ['bash', '-c', 'cd ' . $buildDir . ' && rm ./' . $file]; } $this->process($cmd); $this->output->writeln('<info>' . $file . ' ... [DELETED]</info>'); } catch (\Exception $e) { $this->output->writeln('<error>' . $e->getMessage() . '</error>'); } } } protected function updateBuildVersion(string $version, string $buildDir) : void { $slug = Config::get('plugin.slug'); $pluginFile = $buildDir . '/' . $slug . '.php'; $pluginFileContents = \file_get_contents($pluginFile); $pluginFileContents = \preg_replace('/Version: (.*)/', 'Version: ' . $version, $pluginFileContents); \file_put_contents($pluginFile, $pluginFileContents); $pluginConfigFile = $buildDir . '/config/plugin.php'; $pluginConfigFileContents = \file_get_contents($pluginConfigFile); $pluginConfigFileContents = \preg_replace('/(\'version\' => \\s*\')([0-9\\.]+)(\')/', '\'version\' => \'' . $version . '\'', $pluginConfigFileContents); \file_put_contents($pluginConfigFile, $pluginConfigFileContents); $this->output->writeln('<info>Version updated to - ' . $version . ' [DONE]</info>'); } protected function archive(string $outputDir, string $archiveName, string $ext = 'zip') : void { $this->output->writeln('<comment>Archiving the build ...</comment>'); $supportedFormats = ['zip', 'tar']; if (!\in_array($ext, $supportedFormats)) { $this->output->writeln('<error>Unsupported archive format</error>'); return; } $archive = $archiveName . '.' . $ext; if ($ext === 'zip') { $cmd = ['bash', '-c', 'cd ' . $outputDir . ' && zip -r ' . $archive . ' ' . $archiveName . '/.']; } if ($ext === 'tar') { $cmd = ['bash', '-c', 'cd ' . $outputDir . ' && tar -cvf ' . $archive . ' ' . $archiveName . '/.']; } $cmd[2] = $cmd[2] . ' && rm -rf ./' . $archiveName; $this->process($cmd); $this->output->writeln('<info>Archived [DONE]</info>'); } } src/Commands/MigrateCommand.php 0000777 00000001344 15251357345 0012517 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\DB\Migration\Migrator; class MigrateCommand extends BaseCommand { protected function configure() { $this->setName('db:migrate')->setDescription('Run the database migrations')->setHelp('This command allows you to run the database migrations.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $migrator = new Migrator(WPDRILL_ROOT_PATH . '/database/migrations', $input, $output); $migrator->run(); return Command::SUCCESS; } } src/Commands/ViewCacheCommand.php 0000777 00000002051 15251357345 0012761 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\Plugin; use Rvx\WPDrill\Views\ViewManager; class ViewCacheCommand extends BaseCommand { protected ViewManager $view; public function __construct(Plugin $plugin, ?string $name = null) { $this->view = new ViewManager($plugin); parent::__construct($name); } protected function configure() { $this->setName('view:cache')->setDescription('Compiled and cache all the twig files')->setHelp('This command allows compiled and cached all the twig files.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $output->writeln('<comment>Compiling and caching all the twig files...</comment>'); $this->view->compile(); $output->writeln('<info>Twig files compiled and cached successfully.</info>'); return Command::SUCCESS; } } src/Commands/MigrateRollbackCommand.php 0000777 00000001404 15251357345 0014166 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\DB\Migration\Migrator; class MigrateRollbackCommand extends BaseCommand { protected function configure() { $this->setName('db:rollback')->setDescription('Run the database rollback migrations')->setHelp('This command allows you to run the database migrations rollback.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $migrator = new Migrator(WPDRILL_ROOT_PATH . '/database/migrations', $input, $output); $migrator->rollback(); return Command::SUCCESS; } } src/Commands/MigrateResetCommand.php 0000777 00000001365 15251357345 0013525 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\DB\Migration\Migrator; class MigrateResetCommand extends BaseCommand { protected function configure() { $this->setName('db:reset')->setDescription('Run the database reset migrations')->setHelp('This command allows you to run the database migrations reset.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $migrator = new Migrator(WPDRILL_ROOT_PATH . '/database/migrations', $input, $output); $migrator->reset(); return Command::SUCCESS; } } src/Commands/MigrateRefreshCommand.php 0000777 00000001427 15251357345 0014040 0 ustar 00 <?php namespace Rvx\WPDrill\Commands; use Rvx\Symfony\Component\Console\Command\Command; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\DB\Migration\Migrator; class MigrateRefreshCommand extends BaseCommand { protected function configure() { $this->setName('db:refresh')->setDescription('Run the database refresh migrations')->setHelp('This command allows you to run the database migrations refresh.'); } protected function execute(InputInterface $input, OutputInterface $output) : int { $migrator = new Migrator(WPDRILL_ROOT_PATH . '/database/migrations', $input, $output); $migrator->reset(); $migrator->run(); return Command::SUCCESS; } } src/Routing/Group.php 0000777 00000001524 15251357345 0010612 0 ustar 00 <?php namespace Rvx\WPDrill\Routing; class Group { protected string $prefix = ''; protected string $name = ''; protected $middleware = null; public function __construct($prefix, $name, $middleware) { $this->prefix = $prefix; $this->name = $name; $this->middleware = $middleware; } public function getPrefix() : string { return $this->prefix; } public function getName() : string { return $this->name; } public function getMiddleware() { return $this->middleware; } public function merge(Group $group) { $this->prefix = \rtrim($group->getPrefix(), '/') . '/' . \ltrim($this->prefix, '/'); $this->name = $group->getName() . $this->name; $this->middleware = $group->getMiddleware(); return $this; } } src/Routing/RouteManager.php 0000777 00000007576 15251357345 0012124 0 ustar 00 <?php namespace Rvx\WPDrill\Routing; use Rvx\WPDrill\Plugin; use Rvx\WPDrill\ConfigManager; use Rvx\WPDrill\Contracts\InvokableContract; class RouteManager { protected array $routes = []; protected string $slug = ''; protected string $prefix = ''; protected ConfigManager $config; protected Plugin $app; protected Route $route; protected array $groupStack = []; public function __construct(ConfigManager $config, Plugin $plugin) { $this->app = $plugin; $this->config = $config; $this->slug = \rtrim($this->config->get('plugin.slug'), '/'); } public function addRoute($method, $uri, $action) { $group = null; if ($this->hasGroupStack()) { $group = $this->lastGroupStack(); } $this->route = new Route($method, $uri, $action, $group); $this->routes[] = $this->route; return $this->route; } public function group(array $attributes, callable $callback) { $group = new Group($attributes['prefix'] ?? '', $attributes['name'] ?? '', $attributes['middleware'] ?? ''); if ($this->hasGroupStack()) { $lastGroup = $this->lastGroupStack(); $group = $group->merge($lastGroup); } $this->groupStack[] = $group; $callback($this); \array_pop($this->groupStack); } public function hasGroupStack() { return \count($this->groupStack) > 0; } public function getGroupStack() { return $this->groupStack; } public function lastGroupStack() : Group { return \end($this->groupStack); } public function get(string $uri, $action) { return $this->addRoute('GET', $uri, $action); } public function post(string $uri, $action) { return $this->addRoute('POST', $uri, $action); } public function loadRoutes() { require_once $this->app->getPath('routes/api.php'); // $this->getRoutes(); $this->dispatch(); } public function dispatch() { add_action('rest_api_init', function () { /** * @var Route $route */ foreach ($this->routes as $route) { $instance = null; if (\is_array($route->getAction()) && \count($route->getAction()) == 2) { $class = $this->app->resolve($route->getAction()[0]); $instance = [$class, $route->getAction()[1]]; } if (\is_string($route->getAction()) && \class_exists($route->getAction())) { $instance = $this->app->resolve($route->getAction()); if (!$instance instanceof InvokableContract) { throw new \Exception('Route action must be an instance of InvokableContract or callable or array with 2 elements.'); } } if (!\is_array($route->getAction()) && \is_callable($route->getAction())) { $instance = $route->getAction(); } if ($route->getAction() instanceof InvokableContract) { $instance = $route->getAction(); } register_rest_route($this->slug, $route->getUri(), ['methods' => $route->getMethod(), 'callback' => $instance, 'permission_callback' => $this->resolveMiddleware($route->getMiddleware())]); } }); } protected function resolveMiddleware($middleware) { if (empty($middleware)) { return function () { return \true; }; } if (\is_string($middleware)) { $middleware = $this->app->resolve($middleware); return [$middleware, 'handle']; } if (\is_callable($middleware)) { return $middleware; } throw new \Exception('Middleware can\'t be resolved'); } } src/Routing/Route.php 0000777 00000003023 15251357345 0010610 0 ustar 00 <?php namespace Rvx\WPDrill\Routing; class Route { protected $middleware = null; protected string $method; protected string $uri; protected string $name = ''; protected $action; protected ?Group $group; public function __construct($method, $uri, $action, $group = null) { $this->method = $method; $this->uri = $uri; $this->action = $action; if ($group) { $this->middleware = $group->getMiddleware(); } $this->group = $group; } public function middleware($middleware) : self { $this->middleware = $middleware; return $this; } public function name(string $name) : self { $this->name = $name; return $this; } public function getMethod() : string { return $this->method; } public function getUri() : string { if ($this->group) { return \rtrim($this->group->getPrefix(), '/') . '/' . \ltrim($this->uri, '/'); } return $this->uri; } public function getOriginalUri() : string { return $this->uri; } public function getAction() { return $this->action; } public function getMiddleware() { if ($this->group) { return $this->group->getMiddleware(); } return $this->middleware; } public function getName() : string { if ($this->group) { return $this->group->getName() . $this->name; } return $this->name; } } src/Facades/Shortcode.php 0000777 00000000366 15251357345 0011352 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\Facade; /** * @method static string add(string $code, $handler) */ class Shortcode extends Facade { public static function getFacadeAccessor() { return 'shortcode'; } } src/Facades/View.php 0000777 00000000730 15251357345 0010325 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\Facade; use Rvx\WPDrill\Views\ViewManager; /** * @method static string render(string $view, array $data = []) * @method static void output(string $view, array $data = []) * @method static void print(string $view, array $data = []) * @method static ViewManager templating(bool $enable) */ class View extends Facade { public static function getFacadeAccessor() { return ViewManager::class; } } src/Facades/DB.php 0000777 00000002465 15251357345 0007707 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; use Rvx\WPDrill\Facade; /** * @method static QueryBuilderHandler table(string ...$tables) * @method static QueryBuilderHandler from(string ...$tables) * @method static QueryBuilderHandler select(string ...$columns) * @method static array|object|null get() * @method static \stdClass|null first() * @method static \stdClass|null findAll(string $fieldName, $value) * @method static \stdClass|null find($value, $fieldName = 'id') * @method static int count() * @method static array|string insert(array $data) * @method static array|string update(array $data) * @method static array|string updateOrInsert(array $data) * @method static mixed delete() * @method static QueryBuilderHandler where(string $key, $operator = null, $value = null) * @method static QueryBuilderHandler orWhere(string $key, $operator = null, $value = null) * @method static QueryBuilderHandler whereIn(string $key, array $values) * @method static QueryBuilderHandler whereNull(string $key) * @method static QueryBuilderHandler transaction(\Closure $callback) * @method static void chunk(int $count, callable $callback); */ class DB extends Facade { public static function getFacadeAccessor() { return QueryBuilderHandler::class; } } src/Facades/Config.php 0000777 00000001007 15251357345 0010616 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\Facade; use Rvx\WPDrill\ConfigManager; use Rvx\Noodlehaus\ConfigInterface; /** * @method static mixed get(string $key, mixed $default = null) * @method static void set(string $key, mixed $value) * @method static bool has(string $key) * @method static ConfigInterface merge(ConfigInterface $config) * @method static array all() */ class Config extends Facade { public static function getFacadeAccessor() { return ConfigManager::class; } } src/Facades/Route.php 0000777 00000001123 15251357345 0010506 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\Facade; use Rvx\WPDrill\Routing\RouteManager; use Rvx\Noodlehaus\ConfigInterface; /** * @method static mixed get(string $uri, $action) * @method static mixed post(string $uri, $action) * @method static mixed put(string $uri, $action) * @method static mixed patch(string $uri, $action) * @method static mixed delete(string $uri, $action) * @method static void group(array $attributes, callable $callback) */ class Route extends Facade { public static function getFacadeAccessor() { return RouteManager::class; } } src/Facades/Request.php 0000777 00000001773 15251357345 0011053 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\Facade; use Rvx\Psr\Http\Message\ServerRequestInterface; /** * @method static array getServerParams() * @method static array getAttributes() * @method static mixed getAttribute(string $name, $default = null); * @method static ServerRequestInterface withAttribute(string $name, $value) * @method static ServerRequestInterface withoutAttribute(string $name) * @method static array getCookieParams() * @method static ServerRequestInterface withCookieParams(array $cookies) * @method static array getQueryParams() * @method static ServerRequestInterface withQueryParams(array $query) * @method static array getUploadedFiles() * @method static ServerRequestInterface withUploadedFiles(array $uploadedFiles) * @method static mixed getParsedBody() * @method static ServerRequestInterface withParsedBody(mixed $data) */ class Request extends Facade { public static function getFacadeAccessor() { return ServerRequestInterface::class; } } src/Facades/Menu.php 0000777 00000000736 15251357345 0010325 0 ustar 00 <?php namespace Rvx\WPDrill\Facades; use Rvx\WPDrill\Facade; use Rvx\WPDrill\Menus\Menu as MenuOption; /** * @method static MenuOption add(string $pageTitle, $handler, string $capability) * @method static void remove(string $slug, ?string $submenuSlug = null) * @method static MenuOption group(string $pageTitle, $handler, string $capability, callable $fn) */ class Menu extends Facade { public static function getFacadeAccessor() { return 'menu'; } } src/Facade.php 0000777 00000002210 15251357345 0007223 0 ustar 00 <?php namespace Rvx\WPDrill; abstract class Facade { protected static Plugin $app; protected static array $resolvedInstance = []; public static function setFacadeApplication(Plugin $app) { static::$app = $app; } public static function getFacadeApplication() : Plugin { return static::$app; } public static function getFacadeAccessor() { throw new \RuntimeException('Facade does not implement getFacadeAccessor method.'); } public static function __callStatic($method, $args) { $instance = static::resolveFacadeInstance(static::getFacadeAccessor()); if (!$instance) { throw new \RuntimeException('A facade root has not been set.'); } return \call_user_func_array([$instance, $method], $args); } protected static function resolveFacadeInstance($name) { if (\is_object($name)) { return $name; } if (isset(static::$resolvedInstance[$name])) { return static::$resolvedInstance[$name]; } return static::$resolvedInstance[$name] = static::$app->resolve($name); } } src/Views/TwigFunctions.php 0000777 00000000704 15251357345 0011766 0 ustar 00 <?php namespace Rvx\WPDrill\Views; use Rvx\Twig\Extension\AbstractExtension; use Rvx\WPDrill\Facades\Config; class TwigFunctions extends AbstractExtension { public function getFunctions() { $functions = Config::get('view.functions', []); $twigFuncs = []; foreach ($functions as $name => $function) { $twigFuncs[] = new \Rvx\Twig\TwigFunction($name, $function); } return $twigFuncs; } } src/Views/ViewManager.php 0000777 00000010116 15251357345 0011366 0 ustar 00 <?php namespace Rvx\WPDrill\Views; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use RegexIterator; use Rvx\Twig\Environment; use Rvx\Twig\Lexer; use Rvx\Twig\Loader\FilesystemLoader; use Rvx\WPDrill\Exception; use Rvx\WPDrill\Facades\Config; use Rvx\WPDrill\Plugin; class ViewManager { protected Plugin $plugin; protected Environment $twig; protected bool $enableTemplating = \true; protected string $templateExtension; protected string $templatePath; protected FilesystemLoader $loader; public function __construct(Plugin $plugin) { $this->plugin = $plugin; $this->enableTemplating = Config::get('view.enable_templating', \true); $this->templateExtension = Config::get('view.template_extension', 'twig'); $this->templateExtension = '.' . $this->templateExtension; $this->templatePath = $this->plugin->getPath(Config::get('view.template_path', 'resources/views')); $this->init(); } protected function init() { $this->loader = new FilesystemLoader($this->templatePath); $twigConfig = ['cache' => $this->plugin->getPath(Config::get('view.cache_path', 'storage/cache/views')), 'cache_lifetime' => Config::get('view.cache_lifetime', 0)]; if (!$this->plugin->isProduction()) { $twigConfig['debug'] = \true; $twigConfig['auto_reload'] = \true; } $this->twig = new Environment($this->loader, $twigConfig); $this->twig->addExtension(new TwigFunctions()); $lexer = new Lexer($this->twig, ['tag_comment' => Config::get('view.lexer.tag_comment', ['{#', '#}']), 'tag_block' => Config::get('view.lexer.tag_block', ['{%', '%}']), 'tag_variable' => Config::get('view.lexer.tag_variable', ['{{', '}}']), 'interpolation' => Config::get('view.lexer.interpolation', ['#{', '}'])]); $this->twig->setLexer($lexer); } public function templating(bool $enable) : self { $this->enableTemplating = $enable; return $this; } protected function makeEnableTemplatingAsDefault() : void { $this->enableTemplating = Config::get('view.enable_templating', \true); } public function render(string $view, array $data = []) : string { if ($this->enableTemplating) { $this->makeEnableTemplatingAsDefault(); return $this->renderTwig($view, $data); } $this->makeEnableTemplatingAsDefault(); return $this->renderRaw($view, $data); } protected function renderTwig(string $view, array $data = []) : string { return $this->twig->render($view . $this->templateExtension, $data); } public function renderRaw(string $view, array $data = []) : string { \ob_start(); \extract($data); require $this->templatePath . '/' . $view . '.php'; return \ob_get_clean(); } public function output(string $view, array $data = []) : void { if ($this->enableTemplating) { $this->makeEnableTemplatingAsDefault(); echo $this->renderTwig($view, $data); return; } $this->makeEnableTemplatingAsDefault(); echo $this->renderRaw($view, $data); return; } public function print(string $view, array $data = []) : void { $this->output($view, $data); } public function compile() { $dir = $this->templatePath; $directory = new RecursiveDirectoryIterator($dir); $iterator = new RecursiveIteratorIterator($directory); $regex = new RegexIterator($iterator, '/\\' . $this->templateExtension . '$/'); // Match .twig files foreach ($regex as $file) { $relativePath = \str_replace($dir . \DIRECTORY_SEPARATOR, '', $file->getPathname()); echo $relativePath . " ...\n"; try { // Load each template to compile and cache it $this->twig->load($relativePath); echo $relativePath . ' - [COMPILED]' . "\n"; } catch (Exception $e) { echo $relativePath . ' - [FAILED]' . "\n"; } } } } src/Response.php 0000777 00000010110 15251357345 0007654 0 ustar 00 <?php namespace Rvx\WPDrill; class Response extends \WP_REST_Response { const HTTP_CONTINUE = 100; const HTTP_SWITCHING_PROTOCOLS = 101; const HTTP_PROCESSING = 102; const HTTP_EARLY_HINTS = 103; const HTTP_OK = 200; const HTTP_CREATED = 201; const HTTP_ACCEPTED = 202; const HTTP_NON_AUTHORITATIVE_INFORMATION = 203; const HTTP_NO_CONTENT = 204; const HTTP_RESET_CONTENT = 205; const HTTP_PARTIAL_CONTENT = 206; const HTTP_MULTI_STATUS = 207; const HTTP_ALREADY_REPORTED = 208; const HTTP_IM_USED = 226; const HTTP_MULTIPLE_CHOICES = 300; const HTTP_MOVED_PERMANENTLY = 301; const HTTP_FOUND = 302; const HTTP_SEE_OTHER = 303; const HTTP_NOT_MODIFIED = 304; const HTTP_USE_PROXY = 305; const HTTP_RESERVED = 306; const HTTP_TEMPORARY_REDIRECT = 307; const HTTP_PERMANENTLY_REDIRECT = 308; const HTTP_BAD_REQUEST = 400; const HTTP_UNAUTHORIZED = 401; const HTTP_PAYMENT_REQUIRED = 402; const HTTP_FORBIDDEN = 403; const HTTP_NOT_FOUND = 404; const HTTP_METHOD_NOT_ALLOWED = 405; const HTTP_NOT_ACCEPTABLE = 406; const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; const HTTP_REQUEST_TIMEOUT = 408; const HTTP_CONFLICT = 409; const HTTP_GONE = 410; const HTTP_LENGTH_REQUIRED = 411; const HTTP_PRECONDITION_FAILED = 412; const HTTP_PAYLOAD_TOO_LARGE = 413; const HTTP_URI_TOO_LONG = 414; const HTTP_UNSUPPORTED_MEDIA_TYPE = 415; const HTTP_RANGE_NOT_SATISFIABLE = 416; const HTTP_EXPECTATION_FAILED = 417; const HTTP_IM_A_TEAPOT = 418; const HTTP_MISDIRECTED_REQUEST = 421; const HTTP_UNPROCESSABLE_ENTITY = 422; const HTTP_LOCKED = 423; const HTTP_FAILED_DEPENDENCY = 424; const HTTP_TOO_EARLY = 425; const HTTP_UPGRADE_REQUIRED = 426; const HTTP_PRECONDITION_REQUIRED = 428; const HTTP_TOO_MANY_REQUESTS = 429; const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; const HTTP_INTERNAL_SERVER_ERROR = 500; const HTTP_NOT_IMPLEMENTED = 501; const HTTP_BAD_GATEWAY = 502; const HTTP_SERVICE_UNAVAILABLE = 503; const HTTP_GATEWAY_TIMEOUT = 504; const HTTP_VERSION_NOT_SUPPORTED = 505; const HTTP_VARIANT_ALSO_NEGOTIATES = 506; const HTTP_INSUFFICIENT_STORAGE = 507; const HTTP_LOOP_DETECTED = 508; const HTTP_NOT_EXTENDED = 510; const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; protected int $httpCode = 200; protected int $code = 20000; protected string $message; protected ?string $details = ''; public function success(string $message = '', int $httpCode = self::HTTP_OK, ?int $code = null) : self { $this->httpCode = $httpCode; /** * @var int $code */ $this->code = $code ?? $httpCode * 100; $this->message = $message; $response = ['status' => 'SUCCESS', 'code' => $this->code, 'message' => $message, 'details' => $this->details, 'locale' => get_locale(), 'data' => $this->data]; $this->set_data($response); $this->set_status($httpCode); return $this; } public function fails(string $message = '', int $httpCode = Response::HTTP_BAD_REQUEST, ?int $code = null) : self { $this->httpCode = $httpCode; /** * @var int $code */ $this->code = $code ?? $httpCode * 100; $this->message = $message; $response = ['status' => 'ERROR', 'code' => $this->code, 'message' => $message, 'details' => $this->details, 'locale' => get_locale(), 'data' => $this->data]; $this->set_status($httpCode); $this->set_data($response); return $this; } public function setHeader(string $key, string $value) : self { $this->header($key, $value); return $this; } public function setHeaders(array $headers) : self { foreach ($headers as $key => $value) { $this->header($key, $value); } return $this; } public function details(?string $data = '') : self { $this->details = $data; return $this; } } src/Menus/Menu.php 0000777 00000004500 15251357345 0010057 0 ustar 00 <?php namespace Rvx\WPDrill\Menus; class Menu { protected string $pageTitle = ''; protected string $name = ''; protected string $capability = ''; protected string $slug = ''; protected $handler = null; protected ?int $position = null; protected string $icon = ''; protected string $parentSlug = ''; public function __construct(string $pageTitle, $handler, $capability) { $this->pageTitle = $pageTitle; $this->name = $pageTitle; $this->capability = $capability; $this->slug = $this->toUrlParam($pageTitle); $this->handler = $handler; } public function name(string $name) : self { $this->name = $name; return $this; } public function capability(string $capability) : self { $this->capability = $capability; return $this; } public function slug(string $slug) : self { $this->slug = $slug; return $this; } public function position(int $position) : self { $this->position = $position; return $this; } public function icon(string $icon) : self { $this->icon = $icon; return $this; } public function parentSlug(string $slug) : self { $this->parentSlug = $slug; return $this; } public function getPageTitle() : string { return $this->pageTitle; } public function getName() : string { return $this->name; } public function getCapability() : string { return $this->capability; } public function getSlug() : string { return $this->slug; } public function getHandler() { return $this->handler; } public function getPosition() : ?int { return $this->position; } public function getIcon() : string { return $this->icon; } public function getParentSlug() : string { return $this->parentSlug; } public function hasParent() : bool { return !empty($this->parentSlug); } protected function toSnakeCase($string) : string { return \strtolower(\preg_replace('/(?<!^)[A-Z]/', '_$0', $string)); } protected function toUrlParam(string $string) : string { return \strtolower(\str_replace([' ', '-'], '_', $string)); } } src/Menus/MenuBuilder.php 0000777 00000004526 15251357345 0011376 0 ustar 00 <?php namespace Rvx\WPDrill\Menus; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Plugin; class MenuBuilder { protected Plugin $plugin; protected ?Menu $group = null; protected array $menus = []; protected Menu $menu; public function __construct(Plugin $plugin) { $this->plugin = $plugin; } public function add(string $pageTitle, $handler, $capability = 'read') : Menu { if (\is_string($handler) && \class_exists($handler)) { $handler = $this->plugin->resolve($handler); if (!$handler instanceof InvokableContract) { throw new \Exception('Handler must be an instance of InvokableContract'); } } if (\is_array($handler) && \count($handler) == 2 && \is_string($handler[0]) && \class_exists($handler[0])) { $instance = $this->plugin->resolve($handler[0]); $handler = [$instance, $handler[1]]; } $this->menu = new Menu($pageTitle, $handler, $capability); $this->menus[] = $this->menu; if ($this->group) { $this->menu->parentSlug($this->group->getSlug()); $this->menu->slug($this->group->getSlug() . '_' . $this->menu->getSlug()); } return $this->menu; } public function remove(string $slug, string $submenuSlug = null) { if ($submenuSlug) { remove_submenu_page($slug, $submenuSlug); } else { remove_menu_page($slug); } } public function group(string $pageTitle, $handler, $capability, callable $fn) { $this->group = $this->add($pageTitle, $handler, $capability); $fn($this); $this->group = null; } public function register() { /** * @var Menu $menu */ foreach ($this->menus as $menu) { if ($menu->hasParent()) { add_submenu_page($menu->getParentSlug(), $menu->getPageTitle(), $menu->getName(), $menu->getCapability(), $menu->getSlug(), $menu->getHandler(), $menu->getPosition()); } else { add_menu_page($menu->getPageTitle(), $menu->getName(), $menu->getCapability(), $menu->getSlug(), $menu->getHandler(), $menu->getIcon(), $menu->getPosition()); } } } public function currentGroup() : ?Menu { return $this->group; } } src/DB/Connection.php 0000777 00000006701 15251357345 0010455 0 ustar 00 <?php namespace Rvx\WPDrill\DB; use Rvx\Viocon\Container; use Rvx\WPDrill\DB\QueryBuilder\Adapters\Mysql; use Rvx\WPDrill\DB\EventHandler; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; class Connection { /** * @var Container */ protected $container; /** * @var string */ protected $adapter; /** * @var array */ protected $adapterConfig; /** * @var \wpdb $wpdb */ protected $dbInstance; /** * @var \wpdb $wpdb */ protected $wpdb; /** * @var Connection */ protected static $storedConnection; /** * @var EventHandler */ protected $eventHandler; /** * @param $wpdb * @param array $adapterConfig * @param null|string $alias * @param null|Container $container */ public function __construct($wpdb, array $config = array(), $alias = null, Container $container = null) { $container = $container ?: new Container(); $this->container = $container; $this->wpdb = $wpdb; $this->setAdapter()->setAdapterConfig($config)->connect(); // Create event dependency $this->eventHandler = $this->container->build(EventHandler::class); if ($alias) { $this->createAlias($alias); } } /** * Create an easily accessible query builder alias * * @param $alias */ public function createAlias($alias) { \class_alias(AliasFacade::class, $alias); $builder = $this->container->build(QueryBuilderHandler::class, array($this)); AliasFacade::setQueryBuilderInstance($builder); } /** * Returns an instance of Query Builder */ public function getQueryBuilder() { return $this->container->build(QueryBuilderHandler::class, array($this)); } /** * Create the connection adapter */ protected function connect() { $this->setDbInstance($this->wpdb); // Preserve the first database connection with a static property if (!static::$storedConnection) { static::$storedConnection = $this; } } /** * @param $db * * @return $this */ public function setDbInstance($db) { $this->dbInstance = $db; return $this; } /** * @return \wpdb */ public function getDbInstance() { return $this->dbInstance; } /** * @param $adapter * * @return $this */ public function setAdapter($adapter = Mysql::class) { $this->adapter = $adapter; return $this; } /** * @return string */ public function getAdapter() { return $this->adapter; } /** * @param array $adapterConfig * * @return $this */ public function setAdapterConfig(array $adapterConfig) { $this->adapterConfig = $adapterConfig; return $this; } /** * @return array */ public function getAdapterConfig() { return $this->adapterConfig; } /** * @return Container */ public function getContainer() { return $this->container; } /** * @return EventHandler */ public function getEventHandler() { return $this->eventHandler; } /** * @return Connection */ public static function getStoredConnection() { return static::$storedConnection; } } src/DB/Migration/Sql.php 0000777 00000002077 15251357345 0011050 0 ustar 00 <?php namespace Rvx\WPDrill\DB\Migration; class Sql { protected string $sql = ''; public function __construct(string $sql) { $this->sql = $this->validate($sql); } public function __toString() : string { return $this->sql; } protected function validate($query) : string { // Remove comments $query = \preg_replace('/(--.*)|(#.*)/', '', $query); // Check if the query contains certain keywords $keywords = array('SELECT', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'ALTER', 'DROP', 'TRUNCATE', 'GRANT', 'REVOKE', 'COMMIT', 'ROLLBACK'); $result = \false; foreach ($keywords as $keyword) { if (\stripos($query, $keyword) !== \false) { $result = $result | \true; } } if (!$result) { throw new \Exception('Invalid SQL query'); } return $query; // Query is considered valid } public function concat(self $sql) : self { $this->sql .= $sql->__toString(); return $this; } } src/DB/Migration/Migration.php 0000777 00000004156 15251357345 0012242 0 ustar 00 <?php namespace Rvx\WPDrill\DB\Migration; use Rvx\WPDrill\Contracts\MigrationContract; use Rvx\WPDrill\Facades\Config; abstract class Migration implements MigrationContract { public function __construct() { } protected function table(string $name) : string { global $wpdb; return $wpdb->prefix . (\rtrim(\str_replace('-', '_', \strtolower(Config::get('plugin.prefix'))), '_') . '_') . $name; } public function createTable(string $name, array $columns) : Sql { $query = "CREATE TABLE IF NOT EXISTS {$this->table($name)} ("; foreach ($columns as $key => $value) { \end($columns); if ($key === \key($columns)) { $query .= "{$key} {$value}"; continue; } $query .= "{$key} {$value}, "; } $query .= ")"; return new Sql($query); } public function dropTable(string $name) : Sql { $query = "DROP TABLE IF EXISTS {$this->table($name)}"; return new Sql($query); } public function addColumns(string $table, array $columns) : Sql { $query = "ALTER TABLE {$this->table($table)} ADD "; $query .= \implode(', ADD ', $columns); return new Sql($query); } public function dropColumns(string $table, array $columns) : Sql { $query = "ALTER TABLE {$this->table($table)} DROP COLUMN "; $query .= \implode(', DROP COLUMN ', $columns); return new Sql($query); } public function renameColumns(string $table, array $columns) : Sql { $query = "ALTER TABLE {$this->table($table)} CHANGE "; $query .= \implode(', CHANGE ', $columns); return new Sql($query); } public function updateTable(string $table, array $columns) : Sql { $query = "ALTER TABLE {$this->table($table)} "; $query .= \implode(', ', $columns); return new Sql($query); } public function renameTable(string $oldName, string $newName) : Sql { $query = "RENAME TABLE {$this->table($oldName)} TO {$this->table($newName)}"; return new Sql($query); } } src/DB/Migration/Migrator.php 0000777 00000020106 15251357345 0012066 0 ustar 00 <?php namespace Rvx\WPDrill\DB\Migration; use Rvx\Symfony\Component\Console\Input\InputInterface; use Rvx\Symfony\Component\Console\Output\OutputInterface; use Rvx\WPDrill\Contracts\MigrationContract; use Rvx\WPDrill\Facades\Config; class Migrator { private string $migrationPath; protected array $migrationFiles = []; protected array $migrationNames = []; protected ?InputInterface $input = null; protected ?OutputInterface $output = null; private \wpdb $db; public function __construct(string $migrationPath, InputInterface $input = null, OutputInterface $output = null) { global $wpdb; $this->input = $input; $this->output = $output; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $this->migrationPath = $migrationPath; $this->db = $wpdb; } public function getMigrationInstances(array $files) : array { $migrationInstances = []; foreach ($files as $key => $file) { $file = $this->getMigrationPath($file . '.php'); if (!\file_exists($file)) { continue; } $fileInfo = \pathinfo($file); require_once $file; if (!\class_exists($fileInfo['filename'])) { continue; } $instance = new $fileInfo['filename'](); if (!$instance instanceof MigrationContract) { continue; } $migrationInstances[$fileInfo['filename']] = $instance; } return $migrationInstances; } protected function getAlreadyExecutedMigrations() { $query = "SELECT migration FROM {$this->getMigrationTableName()}"; $result = $this->db->get_results($query); return \array_column($result, 'migration'); } protected function getNeedToMigrations() : array { $alreadyExecutedMigrations = $this->getAlreadyExecutedMigrations(); $migrationFiles = $this->getMigrationNames(); return \array_diff($migrationFiles, $alreadyExecutedMigrations); } public function run() { if ($this->output) { $this->output->writeln('<info>Running migrations...</info>'); } $this->createMigrationsTable(); $migrations = $this->getNeedToMigrations(); if (empty($migrations)) { if ($this->output) { $this->output->writeln('<comment>No migrations to run!</comment>'); } return; } $migrationInstances = $this->getMigrationInstances($migrations); $lastBatch = $this->getLastBatch(); foreach ($migrationInstances as $migration) { $this->up($migration); $this->db->insert($this->getMigrationTableName(), ['migration' => \get_class($migration), 'batch' => $lastBatch + 1]); } if ($this->output) { $this->output->writeln('<info>Migration successfully finished!</info>'); } } public function rollback() { if ($this->output) { $this->output->writeln('<info>Rolling back migrations...</info>'); } $lastBatch = $this->getLastBatch(); if ($lastBatch === 0) { if ($this->output) { $this->output->writeln('<comment>No migrations to rollback!</comment>'); } return; } $query = "SELECT migration FROM {$this->getMigrationTableName()} WHERE batch = {$lastBatch}"; $migrations = $this->db->get_results($query, ARRAY_A); $instances = $this->getRollbackInstances(\array_column($migrations, 'migration')); foreach ($instances as $migration) { $this->down($migration); $this->db->delete($this->getMigrationTableName(), ['migration' => \get_class($migration)]); } if ($this->output) { $this->output->writeln('<info>Rollback successfully finished!</info>'); } } public function reset() { if ($this->output) { $this->output->writeln('<info>Resetting migrations...</info>'); } $query = "SELECT migration FROM {$this->getMigrationTableName()} WHERE true"; $migrations = $this->db->get_results($query, ARRAY_A); $instances = $this->getRollbackInstances(\array_column($migrations, 'migration')); foreach ($instances as $migration) { $this->down($migration); } $query = "DROP TABLE IF EXISTS {$this->getMigrationTableName()}"; $this->db->query($query); if ($this->output) { $this->output->writeln('<info>Reset successfully finished!</info>'); } } protected function getRollbackInstances(array $migrations) : array { $migrationInstances = []; foreach ($migrations as $key => $migration) { $migration = $this->getMigrationPath($migration . '.php'); if (!\file_exists($migration)) { continue; } $fileInfo = \pathinfo($migration); require_once $migration; if (!\class_exists($fileInfo['filename'])) { continue; } $instance = new $fileInfo['filename'](); if (!$instance instanceof MigrationContract) { continue; } $migrationInstances[$fileInfo['filename']] = $instance; } return $migrationInstances; } protected function up(MigrationContract $migration) { if ($this->output) { $this->output->writeln('<comment>Migration: </comment> ' . \get_class($migration)); } $query = $migration->up(); require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($query); if ($this->output) { $this->output->writeln('<info>Migrated: </info> ' . \get_class($migration)); } } protected function down(MigrationContract $migration) { if ($this->output) { $this->output->writeln('<comment>Rollback: </comment> ' . \get_class($migration)); } $query = $migration->down(); $this->db->query($query); if ($this->output) { $this->output->writeln('<info>Rollbacked: </info> ' . \get_class($migration)); } } protected function scan() { $files = \glob($this->getMigrationPath() . '/*.php'); foreach ($files as $key => $file) { $fileInfo = \pathinfo($file); if ($fileInfo['extension'] !== 'php') { continue; } $this->migrationFiles[] = $fileInfo['dirname'] . '/' . $fileInfo['filename']; $this->migrationNames[] = $fileInfo['filename']; } } public function isScanned() : bool { return \count($this->migrationFiles) > 0; } protected function getMigrationFiles() : array { if (!$this->isScanned()) { $this->scan(); } return $this->migrationFiles; } protected function getMigrationNames() : array { if (!$this->isScanned()) { $this->scan(); } return $this->migrationNames; } protected function createMigrationsTable() { $query = "CREATE TABLE IF NOT EXISTS {$this->getMigrationTableName()} (\n id INT AUTO_INCREMENT PRIMARY KEY,\n migration VARCHAR(255),\n batch INT\n )"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta($query); } protected function getLastBatch() : int { $query = "SELECT MAX(batch) as max_batch FROM {$this->getMigrationTableName()}"; $result = $this->db->get_row($query, ARRAY_A); return $result['max_batch'] ?? 0; } protected function getMigrationPath(string $path = '') : string { if ($path === '') { return $this->migrationPath; } return $this->migrationPath . '/' . \ltrim($path, '/'); } protected function getMigrationTableName() : string { return $this->db->prefix . (\rtrim(\str_replace('-', '_', \strtolower(Config::get('plugin.prefix'))), '_') . '_') . 'migrations'; } } src/DB/EventHandler.php 0000777 00000004711 15251357345 0010734 0 ustar 00 <?php namespace Rvx\WPDrill\DB; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; use Rvx\WPDrill\DB\QueryBuilder\Raw; class EventHandler { /** * @var array */ protected $events = array(); /** * @var array */ protected $firedEvents = array(); /** * @return array */ public function getEvents() { return $this->events; } /** * @param $event * @param $table * * @return callable|null */ public function getEvent($event, $table = ':any') { if ($table instanceof Raw) { return null; } return isset($this->events[$table][$event]) ? $this->events[$table][$event] : null; } /** * @param $event * @param string $table * @param callable $action * * @return void */ public function registerEvent($event, $table, \Closure $action) { $table = $table ?: ':any'; $this->events[$table][$event] = $action; } /** * @param $event * @param string $table * * @return void */ public function removeEvent($event, $table = ':any') { unset($this->events[$table][$event]); } /** * @param QueryBuilderHandler $queryBuilder * @param $event * @return mixed */ public function fireEvents($queryBuilder, $event) { $originalArgs = \func_get_args(); $statements = $queryBuilder->getStatements(); $tables = isset($statements['tables']) ? $statements['tables'] : array(); // Events added with :any will be fired in case of any table, // we are adding :any as a fake table at the beginning. \array_unshift($tables, ':any'); // Fire all events foreach ($tables as $table) { // Fire before events for :any table if ($action = $this->getEvent($event, $table)) { // Make an event id, with event type and table $eventId = $event . $table; // Fire event $handlerParams = $originalArgs; unset($handlerParams[1]); // we do not need $event // Add to fired list $this->firedEvents[] = $eventId; $result = \call_user_func_array($action, $handlerParams); if (!\is_null($result)) { return $result; } } } } } src/DB/AliasFacade.php 0000777 00000001731 15251357345 0010471 0 ustar 00 <?php namespace Rvx\WPDrill\DB; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; /** * This class gives the ability to access non-static methods statically * * Class AliasFacade * * @package WpFluent */ class AliasFacade { /** * @var QueryBuilderHandler */ protected static $queryBuilderInstance; /** * @param $method * @param $args * * @return mixed */ public static function __callStatic($method, $args) { if (!static::$queryBuilderInstance) { static::$queryBuilderInstance = new QueryBuilderHandler(); } // Call the non-static method from the class instance return \call_user_func_array(array(static::$queryBuilderInstance, $method), $args); } /** * @param QueryBuilderHandler $queryBuilderInstance */ public static function setQueryBuilderInstance($queryBuilderInstance) { static::$queryBuilderInstance = $queryBuilderInstance; } } src/DB/QueryBuilder/TransactionHaltException.php 0000777 00000000145 15251357345 0015743 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; class TransactionHaltException extends \Exception { } src/DB/QueryBuilder/JoinBuilder.php 0000777 00000002011 15251357345 0013166 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; class JoinBuilder extends QueryBuilderHandler { /** * @param $key * @param $operator * @param $value * * @return $this */ public function on($key, $operator, $value) { return $this->joinHandler($key, $operator, $value, 'AND'); } /** * @param $key * @param $operator * @param $value * * @return $this */ public function orOn($key, $operator, $value) { return $this->joinHandler($key, $operator, $value, 'OR'); } /** * @param $key * @param null $operator * @param null $value * @param string $joiner * * @return $this */ protected function joinHandler($key, $operator = null, $value = null, $joiner = 'AND') { $key = $this->addTablePrefix($key); $value = $this->addTablePrefix($value); $this->statements['criteria'][] = \compact('key', 'operator', 'value', 'joiner'); return $this; } } src/DB/QueryBuilder/Adapters/BaseAdapter.php 0000777 00000036353 15251357345 0014716 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder\Adapters; use Rvx\WPDrill\DB\Connection; use Rvx\WPDrill\DB\Exception; use Rvx\WPDrill\DB\QueryBuilder\Raw; abstract class BaseAdapter { /** * @var \WPDrill\DB\Connection */ protected $connection; /** * @var \Viocon\Container */ protected $container; public function __construct(Connection $connection) { $this->connection = $connection; $this->container = $this->connection->getContainer(); } /** * Build select query string and bindings * * @param $statements * * @throws Exception * @return array */ public function select($statements) { if (!\array_key_exists('tables', $statements)) { throw new Exception('No table specified.', 3); } elseif (!\array_key_exists('selects', $statements)) { $statements['selects'][] = '*'; } // From $tables = $this->arrayStr($statements['tables'], ', '); // Select $selects = $this->arrayStr($statements['selects'], ', '); // Wheres list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE'); // Group bys $groupBys = ''; if (isset($statements['groupBys']) && ($groupBys = $this->arrayStr($statements['groupBys'], ', '))) { $groupBys = 'GROUP BY ' . $groupBys; } // Order bys $orderBys = ''; if (isset($statements['orderBys']) && \is_array($statements['orderBys'])) { foreach ($statements['orderBys'] as $orderBy) { $orderBys .= $this->wrapSanitizer($orderBy['field']) . ' ' . $orderBy['type'] . ', '; } if ($orderBys = \trim($orderBys, ', ')) { $orderBys = 'ORDER BY ' . $orderBys; } } // Limit and offset $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : ''; $offset = isset($statements['offset']) ? 'OFFSET ' . $statements['offset'] : ''; // Having list($havingCriteria, $havingBindings) = $this->buildCriteriaWithType($statements, 'havings', 'HAVING'); // Joins $joinString = $this->buildJoin($statements); $sqlArray = array('SELECT' . (isset($statements['distinct']) ? ' DISTINCT' : ''), $selects, 'FROM', $tables, $joinString, $whereCriteria, $groupBys, $havingCriteria, $orderBys, $limit, $offset); $sql = $this->concatenateQuery($sqlArray); $bindings = \array_merge($whereBindings, $havingBindings); return \compact('sql', 'bindings'); } /** * Build just criteria part of the query * * @param $statements * @param bool $bindValues * * @return array */ public function criteriaOnly($statements, $bindValues = \true) { $sql = $bindings = array(); if (!isset($statements['criteria'])) { return \compact('sql', 'bindings'); } list($sql, $bindings) = $this->buildCriteria($statements['criteria'], $bindValues); return \compact('sql', 'bindings'); } /** * Build a generic insert/ignore/replace query * * @param $statements * @param array $data * * @return array * @throws Exception */ private function doInsert($statements, array $data, $type) { if (!isset($statements['tables'])) { throw new Exception('No table specified', 3); } $table = \end($statements['tables']); $bindings = $keys = $values = array(); foreach ($data as $key => $value) { $keys[] = $key; if ($value instanceof Raw) { $values[] = (string) $value; } else { $values[] = '?'; $bindings[] = $value; } } $sqlArray = array($type . ' INTO', $this->wrapSanitizer($table), '(' . $this->arrayStr($keys, ',') . ')', 'VALUES', '(' . $this->arrayStr($values, ',', \false) . ')'); if (isset($statements['onduplicate'])) { if (\count($statements['onduplicate']) < 1) { throw new Exception('No data given.', 4); } list($updateStatement, $updateBindings) = $this->getUpdateStatement($statements['onduplicate']); $sqlArray[] = 'ON DUPLICATE KEY UPDATE ' . $updateStatement; $bindings = \array_merge($bindings, $updateBindings); } $sql = $this->concatenateQuery($sqlArray); return \compact('sql', 'bindings'); } /** * Build Insert query * * @param $statements * @param array $data * * @return array * @throws Exception */ public function insert($statements, array $data) { return $this->doInsert($statements, $data, 'INSERT'); } /** * Build Insert Ignore query * * @param $statements * @param array $data * * @return array * @throws Exception */ public function insertIgnore($statements, array $data) { return $this->doInsert($statements, $data, 'INSERT IGNORE'); } /** * Build Insert Ignore query * * @param $statements * @param array $data * * @return array * @throws Exception */ public function replace($statements, array $data) { return $this->doInsert($statements, $data, 'REPLACE'); } /** * Build fields assignment part of SET ... or ON DUBLICATE KEY UPDATE ... statements * * @param array $data * * @return array */ private function getUpdateStatement($data) { $bindings = array(); $statement = ''; foreach ($data as $key => $value) { if ($value instanceof Raw) { $statement .= $this->wrapSanitizer($key) . '=' . $value . ','; } else { $statement .= $this->wrapSanitizer($key) . '=?,'; $bindings[] = $value; } } $statement = \trim($statement, ','); return array($statement, $bindings); } /** * Build update query * * @param $statements * @param array $data * * @return array * @throws Exception */ public function update($statements, array $data) { if (!isset($statements['tables'])) { throw new Exception('No table specified', 3); } elseif (\count($data) < 1) { throw new Exception('No data given.', 4); } $table = \end($statements['tables']); // Update statement list($updateStatement, $bindings) = $this->getUpdateStatement($data); // Wheres list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE'); // Limit $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : ''; $sqlArray = array('UPDATE', $this->wrapSanitizer($table), 'SET ' . $updateStatement, $whereCriteria, $limit); $sql = $this->concatenateQuery($sqlArray); $bindings = \array_merge($bindings, $whereBindings); return \compact('sql', 'bindings'); } /** * Build delete query * * @param $statements * * @return array * @throws Exception */ public function delete($statements) { if (!isset($statements['tables'])) { throw new Exception('No table specified', 3); } $table = \end($statements['tables']); // Wheres list($whereCriteria, $whereBindings) = $this->buildCriteriaWithType($statements, 'wheres', 'WHERE'); // Limit $limit = isset($statements['limit']) ? 'LIMIT ' . $statements['limit'] : ''; $sqlArray = array('DELETE FROM', $this->wrapSanitizer($table), $whereCriteria); $sql = $this->concatenateQuery($sqlArray); $bindings = $whereBindings; return \compact('sql', 'bindings'); } /** * Array concatenating method, like implode. * But it does wrap sanitizer and trims last glue * * @param array $pieces * @param $glue * @param bool $wrapSanitizer * * @return string */ protected function arrayStr(array $pieces, $glue, $wrapSanitizer = \true) { $str = ''; foreach ($pieces as $key => $piece) { if ($wrapSanitizer) { $piece = $this->wrapSanitizer($piece); } if (!\is_int($key)) { $piece = ($wrapSanitizer ? $this->wrapSanitizer($key) : $key) . ' AS ' . $piece; } $str .= $piece . $glue; } return \trim($str, $glue); } /** * Join different part of queries with a space. * * @param array $pieces * * @return string */ protected function concatenateQuery(array $pieces) { $str = ''; foreach ($pieces as $piece) { $str = \trim($str) . ' ' . \trim($piece); } return \trim($str); } /** * Build generic criteria string and bindings from statements, like "a = b and c = ?" * * @param $statements * @param bool $bindValues * * @return array */ protected function buildCriteria($statements, $bindValues = \true) { $criteria = ''; $bindings = array(); foreach ($statements as $statement) { $key = $this->wrapSanitizer($statement['key']); $value = $statement['value']; if (\is_null($value) && $key instanceof \Closure) { // We have a closure, a nested criteria // Build a new NestedCriteria class, keep it by reference so any changes made // in the closure should reflect here $nestedCriteria = $this->container->build('Rvx\\WPDrill\\DB\\QueryBuilder\\NestedCriteria', array($this->connection)); $nestedCriteria =& $nestedCriteria; // Call the closure with our new nestedCriteria object $key($nestedCriteria); // Get the criteria only query from the nestedCriteria object $queryObject = $nestedCriteria->getQuery('criteriaOnly', \true); // Merge the bindings we get from nestedCriteria object $bindings = \array_merge($bindings, $queryObject->getBindings()); // Append the sql we get from the nestedCriteria object $criteria .= $statement['joiner'] . ' (' . $queryObject->getSql() . ') '; } elseif (\is_array($value)) { // where_in or between like query $criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator']; switch ($statement['operator']) { case 'BETWEEN': $bindings = \array_merge($bindings, $statement['value']); $criteria .= ' ? AND ? '; break; default: $valuePlaceholder = ''; foreach ($statement['value'] as $subValue) { $valuePlaceholder .= '?, '; $bindings[] = $subValue; } $valuePlaceholder = \trim($valuePlaceholder, ', '); $criteria .= ' (' . $valuePlaceholder . ') '; break; } } elseif ($value instanceof Raw) { $criteria .= "{$statement['joiner']} {$key} {$statement['operator']} {$value} "; } else { // Usual where like criteria if (!$bindValues) { // Specially for joins // We are not binding values, lets sanitize then $value = $this->wrapSanitizer($value); $criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'] . ' ' . $value . ' '; } elseif ($statement['key'] instanceof Raw) { $criteria .= $statement['joiner'] . ' ' . $key . ' '; $bindings = \array_merge($bindings, $statement['key']->getBindings()); } else { // For wheres $valuePlaceholder = '?'; $bindings[] = $value; $criteria .= $statement['joiner'] . ' ' . $key . ' ' . $statement['operator'] . ' ' . $valuePlaceholder . ' '; } } } // Clear all white spaces, and, or from beginning and white spaces from ending $criteria = \preg_replace('/^(\\s?AND ?|\\s?OR ?)|\\s$/i', '', $criteria); return array($criteria, $bindings); } /** * Wrap values with adapter's sanitizer like, '`' * * @param $value * * @return string */ public function wrapSanitizer($value) { // Its a raw query, just cast as string, object has __toString() if ($value instanceof Raw) { return (string) $value; } elseif ($value instanceof \Closure) { return $value; } // Separate our table and fields which are joined with a ".", // like my_table.id $valueArr = \explode('.', $value, 2); foreach ($valueArr as $key => $subValue) { // Don't wrap if we have *, which is not a usual field $valueArr[$key] = \trim($subValue) == '*' ? $subValue : $this->sanitizer . $subValue . $this->sanitizer; } // Join these back with "." and return return \implode('.', $valueArr); } /** * Build criteria string and binding with various types added, like WHERE and Having * * @param $statements * @param $key * @param $type * @param bool $bindValues * * @return array */ protected function buildCriteriaWithType($statements, $key, $type, $bindValues = \true) { $criteria = ''; $bindings = array(); if (isset($statements[$key])) { // Get the generic/adapter agnostic criteria string from parent list($criteria, $bindings) = $this->buildCriteria($statements[$key], $bindValues); if ($criteria) { $criteria = $type . ' ' . $criteria; } } return array($criteria, $bindings); } /** * Build join string * * @param $statements * * @return array|string */ protected function buildJoin($statements) { $sql = ''; if (!\array_key_exists('joins', $statements) || !\is_array($statements['joins'])) { return $sql; } foreach ($statements['joins'] as $joinArr) { if (\is_array($joinArr['table'])) { $mainTable = $joinArr['table'][0]; $aliasTable = $joinArr['table'][1]; $table = $this->wrapSanitizer($mainTable) . ' AS ' . $this->wrapSanitizer($aliasTable); } else { $table = $joinArr['table'] instanceof Raw ? (string) $joinArr['table'] : $this->wrapSanitizer($joinArr['table']); } $joinBuilder = $joinArr['joinBuilder']; $sqlArr = array($sql, \strtoupper($joinArr['type']), 'JOIN', $table, 'ON', $joinBuilder->getQuery('criteriaOnly', \false)->getSql()); $sql = $this->concatenateQuery($sqlArr); } return $sql; } } src/DB/QueryBuilder/Adapters/Mysql.php 0000777 00000000237 15251357345 0013640 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder\Adapters; class Mysql extends BaseAdapter { /** * @var string */ protected $sanitizer = '`'; } src/DB/QueryBuilder/NestedCriteria.php 0000777 00000001006 15251357345 0013670 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; class NestedCriteria extends QueryBuilderHandler { /** * @param $key * @param null $operator * @param null $value * @param string $joiner * * @return $this */ protected function whereHandler($key, $operator = null, $value = null, $joiner = 'AND') { $key = $this->addTablePrefix($key); $this->statements['criteria'][] = \compact('key', 'operator', 'value', 'joiner'); return $this; } } src/DB/QueryBuilder/QueryBuilderHandler.php 0000777 00000064775 15251357345 0014723 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; use Rvx\WPDrill\DB\Connection; use Rvx\WPDrill\DB\Exception; class QueryBuilderHandler { /** * @var \Viocon\Container */ protected $container; /** * @var Connection */ protected $connection; /** * @var array */ protected $statements = array(); /** * @var \wpdb */ protected $db; /** * @var null|string */ protected $dbStatement = null; /** * @var null|string */ protected $tablePrefix = null; /** * @var \WPDrill\DB\QueryBuilder\Adapters\BaseAdapter */ protected $adapterInstance; /** * The PDO fetch parameters to use * * @var array */ protected $fetchParameters = array(\PDO::FETCH_OBJ); /** * @param null|\WPDrill\DB\Connection $connection * * @throws \WPDrill\DB\Exception */ public function __construct(Connection $connection = null) { if (\is_null($connection)) { if (!($connection = Connection::getStoredConnection())) { throw new Exception('No database connection found.', 1); } } $this->connection = $connection; $this->container = $this->connection->getContainer(); $this->db = $this->connection->getDbInstance(); $this->adapter = $this->connection->getAdapter(); $this->adapterConfig = $this->connection->getAdapterConfig(); if (isset($this->adapterConfig['prefix'])) { $this->tablePrefix = $this->adapterConfig['prefix']; } // Query builder adapter instance $this->adapterInstance = $this->container->build($this->adapter, array($this->connection)); } /** * Set the fetch mode * * @param $mode * @return $this */ public function setFetchMode($mode) { $this->fetchParameters = \func_get_args(); return $this; } /** * Fetch query results as object of specified type * * @param $className * @param array $constructorArgs * @return QueryBuilderHandler */ public function asObject($className, $constructorArgs = array()) { \var_dump('need to implement this'); die; return $this->setFetchMode(\PDO::FETCH_CLASS, $className, $constructorArgs); } /** * @param null|\WPDrill\DB\Connection $connection * * @return static */ public function newQuery(Connection $connection = null) { if (\is_null($connection)) { $connection = $this->connection; } return new static($connection); } /** * @param $sql * @param array $bindings * * @return $this */ public function query($sql, $bindings = array()) { $this->dbStatement = $this->container->build('Rvx\\WPDrill\\DB\\QueryBuilder\\QueryObject', array($sql, $bindings))->getRawSql(); return $this; } /** * @param $rawSql * * @return float execution time */ public function statement($rawSql) { $start = \microtime(\true); $this->db->query($rawSql); return \microtime(\true) - $start; } /** * Get all rows * * @return array|object|null * @throws \WPDrill\DB\Exception */ public function get() { $eventResult = $this->fireEvents('before-select'); if (!\is_null($eventResult)) { return $eventResult; } if (\is_null($this->dbStatement)) { $queryObject = $this->getQuery('select'); $this->dbStatement = $queryObject->getRawSql(); } $start = \microtime(\true); $result = $this->db->get_results($this->dbStatement); $executionTime = \microtime(\true) - $start; $this->dbStatement = null; $this->fireEvents('after-select', $result, $executionTime); return $result; } /** * Get first row * * @return \stdClass|null */ public function first() { $this->limit(1); $result = $this->get(); return empty($result) ? null : $result[0]; } /** * @param $value * @param string $fieldName * * @return null|\stdClass */ public function findAll($fieldName, $value) { $this->where($fieldName, '=', $value); return $this->get(); } /** * @param $value * @param string $fieldName * * @return null|\stdClass */ public function find($value, $fieldName = 'id') { $this->where($fieldName, '=', $value); return $this->first(); } /** * Get count of rows * * @return int */ public function count() { // Get the current statements $originalStatements = $this->statements; unset($this->statements['orderBys']); unset($this->statements['limit']); unset($this->statements['offset']); $count = $this->aggregate('count'); $this->statements = $originalStatements; return $count; } /** * @param $type * * @return int */ protected function aggregate($type) { // Get the current selects $mainSelects = isset($this->statements['selects']) ? $this->statements['selects'] : null; // Replace select with a scalar value like `count` $this->statements['selects'] = array($this->raw($type . '(*) as field')); $row = $this->get(); // Set the select as it was if ($mainSelects) { $this->statements['selects'] = $mainSelects; } else { unset($this->statements['selects']); } if (($count = \count($row)) > 1) { return $count; } else { $item = (array) $row[0]; return (int) $item['field']; } } /** * @param string $type * @param array $dataToBePassed * * @return mixed * @throws Exception */ public function getQuery($type = 'select', $dataToBePassed = array()) { $allowedTypes = array('select', 'insert', 'insertignore', 'replace', 'delete', 'update', 'criteriaonly'); if (!\in_array(\strtolower($type), $allowedTypes)) { throw new Exception($type . ' is not a known type.', 2); } $queryArr = $this->adapterInstance->{$type}($this->statements, $dataToBePassed); return $this->container->build('Rvx\\WPDrill\\DB\\QueryBuilder\\QueryObject', array($queryArr['sql'], $queryArr['bindings'])); } /** * @param QueryBuilderHandler $queryBuilder * @param null $alias * * @return Raw */ public function subQuery(QueryBuilderHandler $queryBuilder, $alias = null) { $sql = '(' . $queryBuilder->getQuery()->getRawSql() . ')'; if ($alias) { $sql = $sql . ' as ' . $alias; } return $queryBuilder->raw($sql); } /** * @param $data * * @return array|string * @throws \WPDrill\DB\Exception */ private function doInsert($data, $type) { $eventResult = $this->fireEvents('before-insert'); if (!\is_null($eventResult)) { return $eventResult; } // If first value is not an array // Its not a batch insert if (!\is_array(\current($data))) { $start = \microtime(\true); $queryObject = $this->getQuery($type, $data); $executionTime = $this->statement($queryObject->getRawSql()); $return = $this->db->insert_id; } else { // Its a batch insert $executionTime = 0; $return = array(); foreach ($data as $subData) { $start = \microtime(\true); $queryObject = $this->getQuery($type, $subData); $executionTime = $this->statement($queryObject->getRawSql()); $return[] = $this->db->insert_id; } } $this->fireEvents('after-insert', $return, $executionTime); return $return; } /** * @param $data * * @return array|string */ public function insert($data) { return $this->doInsert($data, 'insert'); } /** * @param $data * * @return array|string */ public function insertIgnore($data) { return $this->doInsert($data, 'insertignore'); } /** * @param $data * * @return array|string */ public function replace($data) { return $this->doInsert($data, 'replace'); } /** * @param $data * * @throws \WPDrill\DB\Exception */ public function update($data) { $eventResult = $this->fireEvents('before-update'); if (!\is_null($eventResult)) { return $eventResult; } $queryObject = $this->getQuery('update', $data); $executionTime = $this->statement($queryObject->getRawSql()); $this->fireEvents('after-update', $queryObject, $executionTime); } /** * @param $data * * @return array|string */ public function updateOrInsert($data) { if ($this->first()) { return $this->update($data); } else { return $this->insert($data); } } /** * @param $data * * @return $this */ public function onDuplicateKeyUpdate($data) { $this->addStatement('onduplicate', $data); return $this; } /** * @return mixed * @throws \WPDrill\DB\Exception */ public function delete() { $eventResult = $this->fireEvents('before-delete'); if (!\is_null($eventResult)) { return $eventResult; } $queryObject = $this->getQuery('delete'); $executionTime = $this->statement($queryObject->getRawSql()); $this->fireEvents('after-delete', $queryObject, $executionTime); } /** * @param string|array $tables Single table or multiple tables * as an array or as multiple parameters * * @return static */ public function table($tables) { if (!\is_array($tables)) { // because a single table is converted to an array anyways, // this makes sense. $tables = array($tables); } $instance = new static($this->connection); $tables = $this->addTablePrefix($tables, \false); $instance->addStatement('tables', $tables); return $instance; } /** * @param $tables * * @return $this */ public function from($tables) { if (!\is_array($tables)) { $tables = array($tables); } $tables = $this->addTablePrefix($tables, \false); $this->addStatement('tables', $tables); return $this; } /** * @param $fields * * @return $this */ public function select($fields) { if (!\is_array($fields)) { $fields = array($fields); } $fields = $this->addTablePrefix($fields); $this->addStatement('selects', $fields); return $this; } /** * @param $fields * * @return $this */ public function selectDistinct($fields) { $this->select($fields); $this->addStatement('distinct', \true); return $this; } /** * @param $field * * @return $this */ public function groupBy($field) { $field = $this->addTablePrefix($field); $this->addStatement('groupBys', $field); return $this; } /** * @param $fields * @param string $defaultDirection * * @return $this */ public function orderBy($fields, $defaultDirection = 'ASC') { if (!\is_array($fields)) { $fields = array($fields); } foreach ($fields as $key => $value) { $field = $key; $type = $value; if (\is_int($key)) { $field = $value; $type = $defaultDirection; } if (!$field instanceof Raw) { $field = $this->addTablePrefix($field); } $this->statements['orderBys'][] = \compact('field', 'type'); } return $this; } /** * @param $limit * * @return $this */ public function limit($limit) { $this->statements['limit'] = $limit; return $this; } /** * @param $offset * * @return $this */ public function offset($offset) { $this->statements['offset'] = $offset; return $this; } /** * @param $key * @param $operator * @param $value * @param string $joiner * * @return $this */ public function having($key, $operator = null, $value = null, $joiner = 'AND') { $key = $this->addTablePrefix($key); $this->statements['havings'][] = \compact('key', 'operator', 'value', 'joiner'); return $this; } /** * @param $key * @param $operator * @param $value * * @return $this */ public function orHaving($key, $operator, $value) { return $this->having($key, $operator, $value, 'OR'); } /** * @param $key * @param $operator * @param $value * * @return $this */ public function where($key, $operator = null, $value = null) { // If two params are given then assume operator is = if (\func_num_args() == 2) { $value = $operator; $operator = '='; } return $this->whereHandler($key, $operator, $value); } /** * @param $key * @param $operator * @param $value * * @return $this */ public function orWhere($key, $operator = null, $value = null) { // If two params are given then assume operator is = if (\func_num_args() == 2) { $value = $operator; $operator = '='; } return $this->whereHandler($key, $operator, $value, 'OR'); } /** * @param $key * @param $operator * @param $value * * @return $this */ public function whereNot($key, $operator = null, $value = null) { // If two params are given then assume operator is = if (\func_num_args() == 2) { $value = $operator; $operator = '='; } return $this->whereHandler($key, $operator, $value, 'AND NOT'); } /** * @param $key * @param $operator * @param $value * * @return $this */ public function orWhereNot($key, $operator = null, $value = null) { // If two params are given then assume operator is = if (\func_num_args() == 2) { $value = $operator; $operator = '='; } return $this->whereHandler($key, $operator, $value, 'OR NOT'); } /** * @param $key * @param array $values * * @return $this */ public function whereIn($key, $values) { return $this->whereHandler($key, 'IN', $values, 'AND'); } /** * @param $key * @param array $values * * @return $this */ public function whereNotIn($key, $values) { return $this->whereHandler($key, 'NOT IN', $values, 'AND'); } /** * @param $key * @param array $values * * @return $this */ public function orWhereIn($key, $values) { return $this->whereHandler($key, 'IN', $values, 'OR'); } /** * @param $key * @param array $values * * @return $this */ public function orWhereNotIn($key, $values) { return $this->whereHandler($key, 'NOT IN', $values, 'OR'); } /** * @param $key * @param $valueFrom * @param $valueTo * * @return $this */ public function whereBetween($key, $valueFrom, $valueTo) { return $this->whereHandler($key, 'BETWEEN', array($valueFrom, $valueTo), 'AND'); } /** * @param $key * @param $valueFrom * @param $valueTo * * @return $this */ public function orWhereBetween($key, $valueFrom, $valueTo) { return $this->whereHandler($key, 'BETWEEN', array($valueFrom, $valueTo), 'OR'); } /** * @param $key * @return QueryBuilderHandler */ public function whereNull($key) { return $this->whereNullHandler($key); } /** * @param $key * @return QueryBuilderHandler */ public function whereNotNull($key) { return $this->whereNullHandler($key, 'NOT'); } /** * @param $key * @return QueryBuilderHandler */ public function orWhereNull($key) { return $this->whereNullHandler($key, '', 'or'); } /** * @param $key * @return QueryBuilderHandler */ public function orWhereNotNull($key) { return $this->whereNullHandler($key, 'NOT', 'or'); } protected function whereNullHandler($key, $prefix = '', $operator = '') { $key = $this->adapterInstance->wrapSanitizer($this->addTablePrefix($key)); return $this->{$operator . 'Where'}($this->raw("{$key} IS {$prefix} NULL")); } /** * @param $table * @param $key * @param $operator * @param $value * @param string $type * * @return $this */ public function join($table, $key, $operator = null, $value = null, $type = 'inner') { if (!$key instanceof \Closure) { $key = function ($joinBuilder) use($key, $operator, $value) { $joinBuilder->on($key, $operator, $value); }; } // Build a new JoinBuilder class, keep it by reference so any changes made // in the closure should reflect here $joinBuilder = $this->container->build('Rvx\\WPDrill\\DB\\QueryBuilder\\JoinBuilder', array($this->connection)); $joinBuilder =& $joinBuilder; // Call the closure with our new joinBuilder object $key($joinBuilder); $table = $this->addTablePrefix($table, \false); // Get the criteria only query from the joinBuilder object $this->statements['joins'][] = \compact('type', 'table', 'joinBuilder'); return $this; } /** * Runs a transaction * * @param $callback * * @return $this */ public function transaction(\Closure $callback) { try { // Begin the PDO transaction $this->db->query('START TRANSACTION'); // Get the Transaction class $transaction = $this->container->build('Rvx\\WPDrill\\DB\\QueryBuilder\\Transaction', array($this->connection)); // Call closure $callback($transaction); // If no errors have been thrown or the transaction wasn't completed within // the closure, commit the changes $this->db->query('COMMIT'); return $this; } catch (TransactionHaltException $e) { // Commit or rollback behavior has been handled in the closure, so exit return $this; } catch (\Exception $e) { // something happened, rollback changes $this->db->query('ROLLBACK'); return $this; } } /** * @param $table * @param $key * @param null $operator * @param null $value * * @return $this */ public function leftJoin($table, $key, $operator = null, $value = null) { return $this->join($table, $key, $operator, $value, 'left'); } /** * @param $table * @param $key * @param null $operator * @param null $value * * @return $this */ public function rightJoin($table, $key, $operator = null, $value = null) { return $this->join($table, $key, $operator, $value, 'right'); } /** * @param $table * @param $key * @param null $operator * @param null $value * * @return $this */ public function innerJoin($table, $key, $operator = null, $value = null) { return $this->join($table, $key, $operator, $value, 'inner'); } /** * Add a raw query * * @param $value * @param $bindings * * @return mixed */ public function raw($value, $bindings = array()) { return $this->container->build('Rvx\\WPDrill\\DB\\QueryBuilder\\Raw', array($value, $bindings)); } /** * Return db instance * * @return \wpdb */ public function db() { return $this->db; } /** * @param Connection $connection * * @return $this */ public function setConnection(Connection $connection) { $this->connection = $connection; return $this; } /** * @return Connection */ public function getConnection() { return $this->connection; } /** * @param $key * @param $operator * @param $value * @param string $joiner * * @return $this */ protected function whereHandler($key, $operator = null, $value = null, $joiner = 'AND') { $key = $this->addTablePrefix($key); $this->statements['wheres'][] = \compact('key', 'operator', 'value', 'joiner'); return $this; } /** * Add table prefix (if given) on given string. * * @param $values * @param bool $tableFieldMix If we have mixes of field and table names with a "." * * @return array|mixed */ public function addTablePrefix($values, $tableFieldMix = \true) { if (\is_null($this->tablePrefix)) { return $values; } // $value will be an array and we will add prefix to all table names // If supplied value is not an array then make it one $single = \false; if (!\is_array($values)) { $values = array($values); // We had single value, so should return a single value $single = \true; } $return = array(); foreach ($values as $key => $value) { // It's a raw query, just add it to our return array and continue next if ($value instanceof Raw || $value instanceof \Closure) { $return[$key] = $value; continue; } // If key is not integer, it is likely a alias mapping, // so we need to change prefix target $target =& $value; if (!\is_int($key)) { $target =& $key; } if (!$tableFieldMix || $tableFieldMix && \strpos($target, '.') !== \false) { $target = $this->tablePrefix . $target; } $return[$key] = $value; } // If we had single value then we should return a single value (end value of the array) return $single ? \end($return) : $return; } /** * @param $key * @param $value */ protected function addStatement($key, $value) { if (!\is_array($value)) { $value = array($value); } if (!\array_key_exists($key, $this->statements)) { $this->statements[$key] = $value; } else { $this->statements[$key] = \array_merge($this->statements[$key], $value); } } /** * @param $event * @param $table * * @return callable|null */ public function getEvent($event, $table = ':any') { return $this->connection->getEventHandler()->getEvent($event, $table); } /** * @param $event * @param string $table * @param callable $action * * @return void */ public function registerEvent($event, $table, \Closure $action) { $table = $table ?: ':any'; if ($table != ':any') { $table = $this->addTablePrefix($table, \false); } $this->connection->getEventHandler()->registerEvent($event, $table, $action); } /** * @param $event * @param string $table * * @return void */ public function removeEvent($event, $table = ':any') { if ($table != ':any') { $table = $this->addTablePrefix($table, \false); } $this->connection->getEventHandler()->removeEvent($event, $table); } /** * @param $event * @return mixed */ public function fireEvents($event) { $params = \func_get_args(); \array_unshift($params, $this); return \call_user_func_array(array($this->connection->getEventHandler(), 'fireEvents'), $params); } /** * @return array */ public function getStatements() { return $this->statements; } /** * Get the paginated rows. * * @param null $perPage * @param array $columns * * @return array */ public function paginate($perPage = null, $columns = array('*')) { $currentPage = \intval($_GET['page']) ?: 1; $perPage = ($perPage ?: \intval($_REQUEST['per_page'])) ?: 15; $skip = $perPage * ($currentPage - 1); $data = (array) $this->select($columns)->limit($perPage)->offset($skip)->get(); $dataCount = \count($data); $from = $dataCount > 0 ? ($currentPage - 1) * $perPage + 1 : null; $to = $dataCount > 0 ? $from + $dataCount - 1 : null; $total = $this->count(); $lastPage = (int) \ceil($total / $perPage); return array('current_page' => $currentPage, 'per_page' => $perPage, 'from' => $from, 'to' => $to, 'last_page' => $lastPage, 'total' => $total, 'data' => $data); } /** * Apply the callback's query changes if the given "value" is true. * * @param mixed $value * @param callable $callback * @param callable $default * @return mixed */ public function when($value, $callback, $default = null) { if ($value) { return $callback($this, $value) ?: $this; } elseif ($default) { return $default($this, $value) ?: $this; } return $this; } /** * @param int $chunk * @param callable $fn * * @return void * @throws Exception */ public function chunk(int $chunk, callable $fn) { $page = 1; $perPage = $chunk; $total = $this->count(); $lastPage = (int) \ceil($total / $perPage); while ($page <= $lastPage) { $data = $this->limit($perPage)->offset(($page - 1) * $perPage)->get(); $fn($data); $page++; } } } src/DB/QueryBuilder/QueryObject.php 0000777 00000004102 15251357345 0013217 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; class QueryObject { /** * @var string */ protected $sql; /** * @var \wpdb */ protected $db; /** * @var array */ protected $bindings = array(); public function __construct($sql, array $bindings) { $this->sql = (string) $sql; $this->bindings = $bindings; global $wpdb; $this->db = $wpdb; } /** * @return string */ public function getSql() { return $this->sql; } /** * @return array */ public function getBindings() { return $this->bindings; } /** * Get the raw/bound sql * * @return string */ public function getRawSql() { return $this->interpolateQuery($this->sql, $this->bindings); } /** * Replaces any parameter placeholders in a query with the value of that * parameter. Useful for debugging. Assumes anonymous parameters from * $params are are in the same order as specified in $query * * Reference: http://stackoverflow.com/a/1376838/656489 * * @param string $query The sql query with parameter placeholders * @param array $params The array of substitution parameters * * @return string The interpolated query */ protected function interpolateQuery($query, $params) { $keys = $placeHolders = []; foreach ($params as $key => $value) { if (\is_string($key)) { $keys[] = '/:' . $key . '/'; } else { $keys[] = '/[?]/'; } $placeHolders[] = $this->getPlaceHolder($value); } $query = \preg_replace($keys, $placeHolders, $query, 1, $count); return $params ? $this->db->prepare($query, $params) : $query; } private function getPlaceHolder($value) { $placeHolder = '%s'; if (\is_int($value)) { $placeHolder = '%d'; } elseif (\is_float($value)) { $placeHolder = '%f'; } return $placeHolder; } } src/DB/QueryBuilder/Raw.php 0000777 00000001026 15251357345 0011516 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; class Raw { /** * @var string */ protected $value; /** * @var array */ protected $bindings; public function __construct($value, $bindings = array()) { $this->value = (string) $value; $this->bindings = (array) $bindings; } public function getBindings() { return $this->bindings; } /** * @return string */ public function __toString() { return (string) $this->value; } } src/DB/QueryBuilder/Transaction.php 0000777 00000000703 15251357345 0013253 0 ustar 00 <?php namespace Rvx\WPDrill\DB\QueryBuilder; class Transaction extends QueryBuilderHandler { /** * Commit the database changes */ public function commit() { $this->db->query('COMMIT'); throw new TransactionHaltException(); } /** * Rollback the database changes */ public function rollback() { $this->db->query('ROLLBACK'); throw new TransactionHaltException(); } } src/DB/LICENSE 0000777 00000002070 15251357345 0006645 0 ustar 00 The MIT License (MIT) Copyright (c) 2016 Muhammad Usman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. src/DB/Exception.php 0000777 00000000111 15251357345 0010301 0 ustar 00 <?php namespace Rvx\WPDrill\DB; class Exception extends \Exception { } src/Providers/ShortcodeServiceProvider.php 0000777 00000001302 15251357345 0015024 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\ServiceProvider; use Rvx\WPDrill\Shortcodes\ShortcodeManager; class ShortcodeServiceProvider extends ServiceProvider { protected ShortcodeManager $shortcode; public function register() : void { $this->shortcode = new ShortcodeManager($this->plugin); $this->plugin->bind('shortcode', function () { return $this->shortcode; }); } public function boot() : void { add_action('init', function () { $shortcode = (require $this->plugin->getPath('bootstrap/shortcodes.php')); $shortcode($this->plugin); $this->shortcode->register(); }); } } src/Providers/MigrationServiceProvider.php 0000777 00000000711 15251357345 0015026 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\DB\Migration\Migrator; use Rvx\WPDrill\Routing\RouteManager; use Rvx\WPDrill\ServiceProvider; class MigrationServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(Migrator::class, function () { return new Migrator($this->plugin->getPath('database/migrations')); }); } public function boot() : void { } } src/Providers/RoutingServiceProvider.php 0000777 00000000764 15251357345 0014534 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\ConfigManager; use Rvx\WPDrill\Routing\RouteManager; use Rvx\WPDrill\ServiceProvider; class RoutingServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(RouteManager::class, function () { $config = $this->plugin->resolve(ConfigManager::class); return new RouteManager($config, $this->plugin); }); } public function boot() : void { } } src/Providers/DBServiceProvider.php 0000777 00000001026 15251357345 0013362 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\DB\QueryBuilder\QueryBuilderHandler; use Rvx\WPDrill\ServiceProvider; class DBServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(QueryBuilderHandler::class, function () { global $wpdb; $connection = new \Rvx\WPDrill\DB\Connection($wpdb, ['prefix' => $wpdb->prefix]); return new QueryBuilderHandler($connection); }); } public function boot() : void { } } src/Providers/ViewServiceProvider.php 0000777 00000000623 15251357345 0014011 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\ServiceProvider; use Rvx\WPDrill\Views\ViewManager; class ViewServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(ViewManager::class, function () { return new \Rvx\WPDrill\Views\ViewManager($this->plugin); }); } public function boot() : void { } } src/Providers/MenuServiceProvider.php 0000777 00000001251 15251357345 0014001 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\Menus\MenuBuilder; use Rvx\WPDrill\ServiceProvider; class MenuServiceProvider extends ServiceProvider { protected MenuBuilder $builder; public function register() : void { $this->plugin->bind('menu', function () { $this->builder = new \Rvx\WPDrill\Menus\MenuBuilder($this->plugin); return $this->builder; }); } public function boot() : void { add_action('admin_menu', function () { $menu = (require $this->plugin->getPath('bootstrap/menu.php')); $menu($this->plugin); $this->builder->register(); }); } } src/Providers/EnqueueServiceProvider.php 0000777 00000011143 15251357345 0014505 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\ConfigManager; use Rvx\WPDrill\Facades\Config; use Rvx\WPDrill\ServiceProvider; class EnqueueServiceProvider extends ServiceProvider { public function register() : void { } public function boot() : void { $adminScripts = Config::get('enqueue.admin.scripts', []); $adminLocalizeScripts = Config::get('enqueue.admin.localize_scripts', []); $adminStyles = Config::get('enqueue.admin.styles', []); $frontendScripts = Config::get('enqueue.frontend.scripts', []); $frontendLocalizeScripts = Config::get('enqueue.frontend.localize_scripts', []); $frontendStyles = Config::get('enqueue.frontend.styles', []); $this->registerAdminEnqueue($adminScripts, $adminStyles); $this->registerFrontendEnqueue($frontendScripts, $frontendStyles); $this->registerAdminLoclizeEnqueue($adminLocalizeScripts); $this->registerFrontendLocalizeEnqueue($frontendLocalizeScripts); $this->registerMediaUploadScript(); $scripts = \array_column(\array_merge($adminScripts, $frontendScripts), null, 'handle'); $styles = \array_column(\array_merge($adminStyles, $frontendStyles), null, 'handle'); $this->addAttributeToScripts($scripts); $this->addAttributeToStyles($styles); } protected function registerAdminEnqueue(array $scripts, array $styles) : void { add_action('admin_enqueue_scripts', function () use($scripts, $styles) { foreach ($scripts as $script) { wp_enqueue_script($script['handle'], $this->plugin->getRelativePath($script['src']), $script['deps'], $script['ver'], $script['in_footer']); } foreach ($styles as $style) { wp_enqueue_style($style['handle'], $this->plugin->getRelativePath($style['src']), $style['deps'], $style['ver'], $style['media']); } }); } protected function registerAdminLoclizeEnqueue(array $adminLocalizeScripts) : void { add_action('admin_enqueue_scripts', function () use($adminLocalizeScripts) { foreach ($adminLocalizeScripts as $adminLocalizeScript) { wp_localize_script($adminLocalizeScript['handle'], $adminLocalizeScript['objectName'], $adminLocalizeScript['data']); } }); } protected function registerFrontendLocalizeEnqueue(array $frontendLocalizeScripts) : void { add_action('wp_enqueue_scripts', function () use($frontendLocalizeScripts) { foreach ($frontendLocalizeScripts as $frontendLocalizeScript) { wp_localize_script($frontendLocalizeScript['handle'], $frontendLocalizeScript['objectName'], $frontendLocalizeScript['data']); } }); } protected function registerFrontendEnqueue(array $scripts, array $styles) : void { add_action('wp_enqueue_scripts', function () use($scripts, $styles) { foreach ($scripts as $script) { wp_enqueue_script($script['handle'], $this->plugin->getRelativePath($script['src']), $script['deps'], $script['ver'], $script['in_footer']); } foreach ($styles as $style) { wp_enqueue_style($style['handle'], $this->plugin->getRelativePath($style['src']), $style['deps'], $style['ver'], $style['media']); } }); } protected function registerMediaUploadScript() : void { add_action('admin_enqueue_scripts', function () { wp_enqueue_media(); }); } protected function addAttributeToScripts(array $scripts) { add_filter('script_loader_tag', function ($tag, $handle) use($scripts) { $script = $scripts[$handle] ?? null; if ($script && \str_contains($tag, '<script')) { $attrs = $script['attributes'] ?? []; foreach ($attrs as $key => $value) { $tag = \str_replace(' src', ' ' . $key . '="' . $value . '" src', $tag); } return $tag; } return $tag; }, 10, 2); } protected function addAttributeToStyles(array $styles) { add_filter('style_loader_tag', function ($tag, $handle) use($styles) { $style = $styles[$handle] ?? null; if ($style && \str_contains($tag, '<link')) { $attrs = $style['attributes'] ?? []; foreach ($attrs as $key => $value) { $tag = \str_replace(' href', ' ' . $key . '="' . $value . '" href', $tag); } return $tag; } return $tag; }, 10, 2); } } src/Providers/CommonServiceProvider.php 0000777 00000001215 15251357345 0014325 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\Facades\Config; use Rvx\WPDrill\ServiceProvider; class CommonServiceProvider extends ServiceProvider { public function register() : void { } public function boot() : void { $postTypes = Config::get('post-types', []); $this->registerPostTypes($postTypes); } protected function registerPostTypes(array $postTypes) : void { foreach ($postTypes as $type => $config) { $cpt = function () use($type, $config) { register_post_type($type, $config); }; add_action('init', $cpt); } } } src/Providers/ConfigServiceProvider.php 0000777 00000000642 15251357345 0014305 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\ConfigManager; use Rvx\WPDrill\ServiceProvider; class ConfigServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(ConfigManager::class, function () { return new \Rvx\WPDrill\ConfigManager($this->plugin->getPath('config')); }); } public function boot() : void { } } src/Providers/RequestServiceProvider.php 0000777 00000001542 15251357345 0014530 0 ustar 00 <?php namespace Rvx\WPDrill\Providers; use Rvx\WPDrill\ConfigManager; use Rvx\WPDrill\Routing\RouteManager; use Rvx\WPDrill\ServiceProvider; use Rvx\Psr\Http\Message\ServerRequestInterface; class RequestServiceProvider extends ServiceProvider { public function register() : void { $this->plugin->bind(ServerRequestInterface::class, function () { $psr17Factory = new \Rvx\Nyholm\Psr7\Factory\Psr17Factory(); $creator = new \Rvx\Nyholm\Psr7Server\ServerRequestCreator( $psr17Factory, // ServerRequestFactory $psr17Factory, // UriFactory $psr17Factory, // UploadedFileFactory $psr17Factory ); return $creator->fromGlobals(); }); } public function boot() : void { } } src/Helpers.php 0000777 00000000461 15251357345 0007470 0 ustar 00 <?php namespace Rvx\WPDrill; use Rvx\WPDrill\Response; class Helpers { public static function rest(array $data) : Response { return new Response($data); } public static function path(array $segment) : string { return \implode(\DIRECTORY_SEPARATOR, $segment); } } src/Shortcodes/ShortcodeManager.php 0000777 00000001727 15251357345 0013436 0 ustar 00 <?php namespace Rvx\WPDrill\Shortcodes; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Contracts\ShortcodeContract; use Rvx\WPDrill\Menus\Menu; use Rvx\WPDrill\Plugin; class ShortcodeManager { protected Plugin $plugin; protected array $shortcodes = []; public function __construct(Plugin $plugin) { $this->plugin = $plugin; } public function add(string $code, $handler) : self { if (\is_string($handler) && \class_exists($handler)) { $handler = $this->plugin->resolve($handler); } if (!$handler instanceof ShortcodeContract) { throw new \Exception('Handler must be an instance of ShortcodeContract'); } $handler = [$handler, 'render']; $this->shortcodes[$code] = $handler; return $this; } public function register() { foreach ($this->shortcodes as $code => $handler) { add_shortcode($code, $handler); } } } src/Plugin.php 0000777 00000012114 15251357345 0007322 0 ustar 00 <?php namespace Rvx\WPDrill; use Rvx\WPDrill\Contracts\InvokableContract; use Rvx\WPDrill\Routing\RouteManager; use Rvx\DI\Container; use Rvx\DI\ContainerBuilder; use Rvx\Psr\Container\ContainerInterface; use Rvx\WPDrill\Helpers; class Plugin { protected static ?self $instance = null; protected string $file; protected static self $app; protected ContainerBuilder $builder; protected Container $container; protected array $events = []; //protected string $file; protected string $path; protected string $relativePath; /** * @var mixed|string */ protected string $version; /** * @var mixed|string */ protected string $name; /** * @var mixed|string */ protected string $slug; /** * @var mixed|string */ protected string $restApiNamespace; protected array $providers = []; protected array $pluginConfig = []; protected bool $isProd = \true; public function __construct(string $file, string $containerClass = Container::class) { $this->file = $file; $this->relativePath = plugin_dir_url($file); $path = \pathinfo($this->file); $this->path = $path['dirname']; $this->builder = new ContainerBuilder($containerClass); $this->pluginConfig = $configs = (require_once $this->getPath(Helpers::path(['config', 'plugin.php']))); $this->version = $configs['version'] ?? '1.0.0'; $this->name = $configs['name'] ?? 'WPDrill'; $this->slug = $configs['slug'] ?? 'corewp'; $this->restApiNamespace = $configs['rest_api_namespace'] ?? 'corewp'; $this->providers = $configs['providers'] ?? []; if (\file_exists($this->getPath('.env.dev'))) { $this->isProd = \false; } static::$instance = $this; } public static function getInstance(?string $file = null) : self { if (self::$instance === null) { if ($file === null) { $file = __FILE__; } self::$instance = new static($file); } return self::$instance; } public function isProduction() : bool { return $this->isProd; } public function make(?callable $fn = null) : void { $providerInstance = []; foreach ($this->providers as $provider) { $provider = new $provider($this); $providerInstance[] = $provider; $provider->register(); } $this->container = $this->builder->build(); foreach ($this->events as $name => $handler) { $this->eventFire($name); } foreach ($providerInstance as $provider) { $provider->boot(); } if ($fn) { $fn($this->resolve(RouteManager::class)); } if (\php_sapi_name() === 'cli') { return; } $initHandlers = $this->pluginConfig['initial_handlers'] ?? []; $this->registerPluginHooks($initHandlers['activated'] ?? null, $initHandlers['deactivated'] ?? null, $initHandlers['uninstalled'] ?? null); } public function bind(string $name, callable $resolver) : void { $this->builder->addDefinitions([$name => $resolver]); } public function getContainer() : ContainerInterface { return $this->container; } public function resolve(string $name) { return $this->container->get($name); } public function registerPluginHooks($activationHandler = null, $deactivationHandler = null, $uninstallHandler = null) : void { if ($activationHandler) { register_activation_hook($this->file, $this->resolveHandler($activationHandler)); } if ($deactivationHandler) { register_deactivation_hook($this->file, $this->resolveHandler($deactivationHandler)); } if ($uninstallHandler) { register_uninstall_hook($this->file, $uninstallHandler); } } public function resolveHandler(string $handler) : InvokableContract { $handler = $this->resolve($handler); if (!$handler instanceof InvokableContract) { throw new \Exception('Handler must be an instance of InvokableContract'); } return $handler; } public function getPath(string $path = '') : string { return \rtrim($this->path, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR . \ltrim($path, \DIRECTORY_SEPARATOR); } public function getRelativePath(string $path = '') : string { return \rtrim($this->relativePath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR . \ltrim($path, \DIRECTORY_SEPARATOR); } public function getVersion() : string { return $this->version; } public function getName() : string { return $this->name; } public function getSlug() : string { return $this->slug; } public function getRestApiNamespace() : string { return $this->restApiNamespace; } public function versionCompare(string $version, string $operator) : bool { return \version_compare($this->getVersion(), $version, $operator); } } src/ConfigManager.php 0000777 00000003440 15251357345 0010566 0 ustar 00 <?php namespace Rvx\WPDrill; use Rvx\Noodlehaus\Exception\EmptyDirectoryException; use Rvx\Noodlehaus\Parser\ParserInterface; class ConfigManager extends \Rvx\Noodlehaus\Config { /** * Loads configuration from file. * * @param string|array $path Filenames or directories with configuration * @param ParserInterface $parser Configuration parser * * @throws EmptyDirectoryException If `$path` is an empty directory */ protected function loadFromFile($path, ParserInterface $parser = null) { $paths = $this->getValidPath($path); $this->data = []; foreach ($paths as $path) { if ($parser === null) { list($filename, $extension) = $this->getFileInfo($path); // Skip the `dist` extension if ($extension === 'dist') { $extension = \array_pop($parts); } // Get file parser $parser = $this->getParser($extension); // Try to load file $this->data[$filename] = $parser->parseFile($path); // Clean parser $parser = null; } else { // Try to load file using specified parser list($filename, $extension) = $this->getFileInfo($path); $this->data[$filename] = $parser->parseFile($path); } } } protected function getFileInfo($path) { $info = \pathinfo($path); $parts = \explode('.', $info['basename']); $extension = \array_pop($parts); $filename = $info['filename']; // Skip the `dist` extension if ($extension === 'dist') { $extension = \array_pop($parts); } return [$filename, $extension]; } } src/Option.php 0000777 00000003465 15251357345 0007345 0 ustar 00 <?php namespace Rvx\WPDrill; class Option { public static function get($keys, $default = null) { if (\is_array($keys)) { return get_options($keys); } return \get_option($keys, $default); } public static function set(string $key, $value) : bool { return \update_option($key, $value); } public static function delete(string $key) : bool { return \delete_option($key); } public static function all() : array { return wp_load_alloptions(); } public static function has(string $key) : bool { return \array_key_exists($key, self::all()); } public static function forget(string $key) : bool { return self::delete($key); } public static function flush() : bool { return wp_cache_delete('alloptions', 'options'); } public static function getPostMeta(int $postId, string $key, $default = null) { return \get_post_meta($postId, $key, \true) ?: $default; } public static function setPostMeta(int $postId, string $key, $value) : bool { return \update_post_meta($postId, $key, $value); } public static function deletePostMeta(int $postId, string $key) : bool { return \delete_post_meta($postId, $key); } public static function allPostMeta(int $postId) : array { return \get_post_meta($postId); } public static function hasPostMeta(int $postId, string $key) : bool { return \array_key_exists($key, self::allPostMeta($postId)); } public static function forgetPostMeta(int $postId, string $key) : bool { return self::deletePostMeta($postId, $key); } public static function flushPostMeta(int $postId) : bool { return \delete_post_meta($postId, ''); } } src/ServiceProvider.php 0000777 00000000431 15251357345 0011176 0 ustar 00 <?php namespace Rvx\WPDrill; abstract class ServiceProvider { protected Plugin $plugin; public function __construct(Plugin $plugin) { $this->plugin = $plugin; } public abstract function register() : void; public abstract function boot() : void; } src/Contracts/MigrationContract.php 0000777 00000000305 15251357345 0013452 0 ustar 00 <?php namespace Rvx\WPDrill\Contracts; use Rvx\WPDrill\DB\Migration\Sql; use Rvx\WPDrill\Plugin; interface MigrationContract { public function up() : Sql; public function down() : Sql; } src/Contracts/InvokableContract.php 0000777 00000000151 15251357345 0013432 0 ustar 00 <?php namespace Rvx\WPDrill\Contracts; interface InvokableContract { public function __invoke(); } src/Contracts/ShortcodeContract.php 0000777 00000000316 15251357345 0013455 0 ustar 00 <?php namespace Rvx\WPDrill\Contracts; use Rvx\WPDrill\DB\Migration\Sql; use Rvx\WPDrill\Plugin; interface ShortcodeContract { public function render(array $attrs, string $content = null) : string; } stubs/helpers.stub 0000777 00000002614 15251357345 0010271 0 ustar 00 <?php use WPDrill\Response; use WPDrill\Plugin; if (!function_exists('#[function-prefix]_plugin')) { function #[function-prefix]_plugin(): \WPDrill\Plugin { return \WPDrill\Plugin::getInstance(); } } if (!function_exists('#[function-prefix]_rest')) { function #[function-prefix]_rest($data): \WPDrill\Response { return new Response($data); } } if (!function_exists('#[function-prefix]_plugin_path')) { function #[function-prefix]_plugin_path(string $path = ''): string { return #[const-prefix]_DIR_PATH . ltrim($path, '/'); } } if (!function_exists('#[function-prefix]_plugin_file')) { function #[function-prefix]_plugin_file(string $path = ''): string { return #[const-prefix]_FILE; } } if (!function_exists('#[function-prefix]_resource_path')) { function #[function-prefix]_resource_path(string $path = ''): string { return #[function-prefix]_plugin_path('resources/' . ltrim($path, '/')); } } if (!function_exists('#[function-prefix]_storage_path')) { function #[function-prefix]_storage_path(string $path = ''): string { return #[function-prefix]_plugin_path('storage/' . ltrim($path, '/')); } } if (!function_exists('#[function-prefix]_plugin')) { function #[function-prefix]_plugin(string $path = ''): Plugin { return Plugin::getInstance(#[const-prefix]_FILE); } } stubs/wpdrill.stub 0000777 00000002052 15251357345 0010300 0 ustar 00 <?php /** * Plugin Name: #[plugin-name] * Plugin URI: https://github.com/wpdrill/framework * Description: A plugin development framework for human * Version: 1.0.0-alpha * Author: Nahid Bin Azhar * Author URI: https://nahid.im/ * Text Domain: #[plugin-slug] * Domain Path: /languages * @package WPDrill * @author Nahid Bin Azhar <nahid.dns@gmail.com> * @copyright Copyright (C) 2024 WPDrill. All rights reserved. * @license GPLv3 or later * @since 1.0.0 */ // don't call the file directly defined( 'ABSPATH' ) || die(); define('#[const-prefix]_DIR_PATH', plugin_dir_path(__FILE__)); define('#[const-prefix]_PREFIX', 'rvx_'); define( '#[const-prefix]_FILE', __FILE__ ); if (php_sapi_name() === 'cli') { return; } function #[function-prefix]_wpdrill_init() { require __DIR__ . '/vendor/autoload.php'; call_user_func(function($bootstrap) { $bootstrap(__FILE__); }, require(__DIR__.'/bootstrap/boot.php')); } #[function-prefix]_wpdrill_init();
| ver. 1.6 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка