Compare commits

..

No commits in common. "master" and "1.2.0" have entirely different histories.

7 changed files with 29 additions and 240 deletions

View file

@ -21,9 +21,3 @@ $post->post_content;
// Update the datetime modified for this post // Update the datetime modified for this post
$post->post_modified = new DateTimeImmutable(); $post->post_modified = new DateTimeImmutable();
``` ```
# Plugins
This library also has support for the following plugins:
Plugin|Versions|Reference
--|--|--
[Redirection](https://wordpress.org/plugins/redirection/)|5.3.10 (limited support)|[Plugins/redirection](/vlw/wp/src/branch/feat/plugin-redirection/src/Plugins/redirection)

6
composer.lock generated
View file

@ -35,11 +35,11 @@
}, },
{ {
"name": "vlw/scaffold", "name": "vlw/scaffold",
"version": "1.7.6", "version": "1.7.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://codeberg.org/vlw/scaffold", "url": "https://codeberg.org/vlw/scaffold",
"reference": "ffd809f76dd50d7a6ee631f21715dca40ec40f44" "reference": "1536079fe384c0cdc8b3814b67318140dbc339ff"
}, },
"require": { "require": {
"vlw/mysql": "3.5.*" "vlw/mysql": "3.5.*"
@ -61,7 +61,7 @@
} }
], ],
"description": "Project scaffolding (primarily) for Reflect and Vegvisir projects", "description": "Project scaffolding (primarily) for Reflect and Vegvisir projects",
"time": "2026-02-24T09:44:05+00:00" "time": "2026-02-11T16:25:22+00:00"
}, },
{ {
"name": "vlw/xenum", "name": "vlw/xenum",

View file

@ -31,7 +31,13 @@
* @return static * @return static
*/ */
public static function current(): static { public static function current(): static {
return static::instance(); return new static(
self::$hostname,
self::$username,
self::$password,
self::$name,
self::$prefix
);
} }
/** /**

View file

@ -1,148 +0,0 @@
<?php
namespace vlw\WP\Plugins\redirection;
use Exception;
use DateTimeImmutable;
use vlw\Scaffold\Database\Model;
use vlw\WP\Database;
use vlw\WP\Plugins\redirection\Tables\{Items, StatusEnum};
require_once "Tables/Items.php";
class Item extends Model {
public static function match(string $subject): array {
$matches = [];
$subject = self::get_pathname($subject);
$query = Database::current()
->from(Database::get_table(Items::TABLE_NAME))
->where([Items::STATUS->value => StatusEnum::ENABLED->value])
->select([
Items::ID->value,
Items::URL->value,
Items::MATCH_URL->value,
Items::REGEX->value
]);
foreach ($query->fetch_all(MYSQLI_ASSOC) as $row) {
// Check if subject is a direct match against the value of URL if its not a RegEx
if (!$row[Items::REGEX->value]) {
if ($subject === $row[Items::URL->value]) {
$matches[] = new static($row[Items::ID->value]);
}
continue;
}
$preg_match = [];
$pattern = str_replace("/", "\\/", $row[Items::URL->value]);
preg_match("/{$pattern}/", $subject, $preg_match);
// This subject matched this RegEx, instance this redirection Item
if (!$preg_match) {
continue;
}
$matches[] = new static($row[Items::ID->value]);
}
return $matches;
}
/**
* Return the pathname of a given URL
*
* @param string $subject
* @return string
*/
private static function get_pathname(string $subject): string {
// Coerce relative URL into absolute so parse_url() does not freak out
if (substr($subject, 0, 4) !== "http") {
$subject = trim($subject);
$subject = "http://example.com/{$subject}/";
}
return parse_url($subject, PHP_URL_PATH);
}
public function __construct(public readonly int $id) {
parent::__construct(
Database::get_table(Items::TABLE_NAME),
Items::values(),
[Items::ID->value => $id]
);
}
public string $url {
get => $this->get(Items::URL->value);
set (string $url) => $this->set(Items::URL->value, $url);
}
public string $match_url {
get => $this->get(Items::URL->value);
set (string $match_url) => $this->set(Items::URL->value, substr($match_url, 0, 2000));
}
public string $match_data {
get => $this->get(Items::MATCH_DATA->value);
set (string $match_data) => $this->set(Items::MATCH_DATA->value, $match_data);
}
public bool $regex {
get => $this->get(Items::REGEX->value);
set (bool $regex) => $this->set(Items::REGEX->value, $regex);
}
public int $position {
get => $this->get(Items::POSITION->value);
set (int $position) => $this->set(Items::POSITION->value, $position);
}
public int $last_count {
get => $this->get(Items::LAST_COUNT->value);
set (int $last_count) => $this->set(Items::LAST_COUNT->value, $last_count);
}
public DateTimeImmutable $last_access {
get => new DateTimeImmutable($this->get(Items::LAST_ACCESS->value));
set (DateTimeImmutable $last_access) => $this->set(Items::LAST_ACCESS->value, $last_access->format(static::DATETIME_FORMAT), $last_access);
}
public int $group_id {
get => $this->get(Items::GROUP_ID->value);
set (int $group_id) => $this->set(Items::GROUP_ID->value, $group_id);
}
public StatusEnum $status {
get => StatusEnum::from($this->get(Items::STATUS->value));
set (StatusEnum $status) => $this->set(Items::STATUS->value, $status->value, $status);
}
public string $action_type {
get => $this->get(Items::MATCH_TYPE->value);
set (string $action_type) => $this->set(Items::ACTION_TYPE->value, substr($action_type, 0, 20));
}
public int $action_code {
get => $this->get(Items::ACTION_CODE->value);
set (int $action_code) => $this->set(Items::ACTION_CODE->value, $action_code);
}
public string $action_data {
get => $this->get(Items::ACTION_DATA->value);
set (string $action_data) => $this->set(Items::ACTION_DATA->value, $action_data);
}
public string $match_type {
get => $this->get(Items::MATCH_TYPE->value);
set (string $match_type) => $this->set(Items::MATCH_TYPE->value, substr($match_type, 0, 20));
}
public string $title {
get => $this->get(Items::TITLE->value);
set (string $title) => $this->set(Items::TITLE->value, $title);
}
}

View file

@ -1,34 +0,0 @@
<?php
namespace vlw\WP\Plugins\redirection\Tables;
use vlw\xEnum;
enum StatusEnum: string {
use xEnum;
case ENABLED = "enabled";
case DISABLED = "disabled";
}
enum Items: string {
use xEnum;
public const TABLE_NAME = "redirection_items";
case ID = "id";
case URL = "url";
case MATCH_URL = "match_url";
case MATCH_DATA = "match_data";
case REGEX = "regex";
case POSITION = "position";
case LAST_COUNT = "last_count";
case LAST_ACCESS = "last_access";
case GROUP_ID = "group_id";
case STATUS = "status";
case ACTION_TYPE = "action_type";
case ACTION_CODE = "action_code";
case ACTION_DATA = "action_data";
case MATCH_TYPE = "match_type";
case TITLE = "title";
}

View file

@ -34,27 +34,6 @@
return $query->num_rows === 1 ? new static($query->fetch_assoc()[Posts::ID->value]) : null; return $query->num_rows === 1 ? new static($query->fetch_assoc()[Posts::ID->value]) : null;
} }
/**
* Create and return a shallow copy of a Post
*
* @param Post $post
* @return static
*/
public static function clone(Post $post): static {
$clone = Post::new($post->post_title);
foreach (Posts::cases() as $column) {
// ID column has to be unique, skip it
if ($column === Posts::ID) {
continue;
}
$clone->{$column->value} = $post->{$column->value};
}
return $clone;
}
/** /**
* Create a new post * Create a new post
* *
@ -187,14 +166,9 @@
set (DateTimeImmutable $post_modified_gmt) => $this->set(Posts::POST_MODIFIED_GMT->value, $post_modified_gmt->format(static::DATETIME_FORMAT), $post_modified_gmt); set (DateTimeImmutable $post_modified_gmt) => $this->set(Posts::POST_MODIFIED_GMT->value, $post_modified_gmt->format(static::DATETIME_FORMAT), $post_modified_gmt);
} }
public string $post_content_filtered { public Post|false|null $post_parent {
get => $this->get(Posts::POST_CONTENT_FILTERED->value); get => $this->get(Posts::POST_PARENT->value) !== 0 ? new self($this->get(Posts::POST_PARENT->value)) : null;
set (string $post_content_filtered) => $this->set(Posts::POST_CONTENT_FILTERED->value, $post_content_filtered); set (Post|false|null $post_parent) => $this->set(Posts::POST_PARENT->value, $post_parent ? $post_parent->id : 0, $post_parent);
}
public ?Post $post_parent {
get => $this->get(Posts::POST_PARENT->value) !== 0 ? new self($this->get(Posts::POST_PARENT->value)) : null;
set (?Post $post_parent) => $this->set(Posts::POST_PARENT->value, $post_parent ? $post_parent->id : 0, $post_parent);
} }
public string $guid { public string $guid {

View file

@ -5,21 +5,17 @@
use Exception; use Exception;
use vlw\MimeTypes\MimeTypes; use vlw\MimeTypes\MimeTypes;
use vlw\WP\Database;
use vlw\WP\Posts\Post; use vlw\WP\Posts\Post;
use vlw\WP\Tables\Posts;
use vlw\WP\Posts\PostMeta; use vlw\WP\Posts\PostMeta;
use function vlw\WP\Support\slugify; use function vlw\WP\Support\slugify;
require_once dirname(__DIR__, 1) . "/Post.php"; require_once dirname(__DIR__, 1) . "/Post.php";
require_once dirname(__DIR__, 1) . "/PostMeta.php"; require_once dirname(__DIR__, 1) . "/PostMeta.php";
require_once dirname(__DIR__, 2) . "/Support/Slugify.php"; require_once dirname(__DIR__, 2) . "/Support/Slugify.php";
require_once dirname(__DIR__, 2) . "/Tables/Posts.php";
class Attachment { class Attachment {
private const POST_TYPE = "attachment"; private const META_KEY_THUMBNAIL_ID = "_thumbnail_id";
private const META_KEY_THUMBNAIL_ID = "_thumbnail_id"; private const META_KEY_FEATURED_MEDIA = "_featured_media";
private const META_KEY_FEATURED_MEDIA = "_featured_media";
private const META_KEY_WP_ATTACHED_FILE = "_wp_attached_file"; private const META_KEY_WP_ATTACHED_FILE = "_wp_attached_file";
public private(set) readonly Post $post; public private(set) readonly Post $post;
@ -32,23 +28,24 @@
* @return Attachment|null * @return Attachment|null
*/ */
public static function from_post_featured(Post $post, bool $thumbnail = true): ?Attachment { public static function from_post_featured(Post $post, bool $thumbnail = true): ?Attachment {
// We didn't find any post meta, let's search the post table for an attachment with this Post as its parent // Check the thumbnail for an attachment ID. This operation is slightly less demanding than unserialize
$query = Database::current() if ($thumbnail) {
->from(Database::get_table("posts")) $post_meta = PostMeta::get_post_meta($post, self::META_KEY_THUMBNAIL_ID);
->where([
Posts::POST_PARENT->value => $post->id,
Posts::POST_TYPE->value => self::POST_TYPE
])
->limit(1)
->select(Posts::ID->value);
// Bail out, we didn't find any valid featured media for this Post if ($post_meta) {
if ($query->num_rows !== 1) { return new static($post_meta->id);
}
}
$post_meta = PostMeta::get_post_meta($post, self::META_KEY_FEATURED_MEDIA);
// Bail out, the target Post does not have any featured media
if (!$post_meta) {
return null; return null;
} }
// We found an attachment // New instance from post ID in featured media serialized object
return new static($query->fetch_assoc()[Posts::ID->value]); return new static((int) unserialize($post_meta->meta_value)[0]);
} }
/** /**