Skip to content
wiki.fftac.org

Helpers - Source Excerpt 17

Back to Helpers

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/themes/spiralist/inc/helpers.php so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/themes/spiralist/inc/helpers.php

$files = [];
    $signature_parts = [];
    $allowed = array_fill_keys(array_map('strtolower', $allowed_extensions), true);

    foreach ($directories as $directory) {
        $base_path = rtrim((string) ($directory['path'] ?? ''), '/\\');
        $base_url = trailingslashit((string) ($directory['url'] ?? ''));
        $entries = $base_path !== '' && is_dir($base_path) ? scandir($base_path) : false;

        if (!is_array($entries) || $base_url === '') {
            continue;
        }

        foreach ($entries as $entry) {
            $filename = trim((string) $entry);
            if ($filename === '' || $filename[0] === '.') {
                continue;
            }

            $extension = strtolower((string) pathinfo($filename, PATHINFO_EXTENSION));
            if (!isset($allowed[$extension])) {
                continue;
            }

            $path = $base_path . DIRECTORY_SEPARATOR . $filename;
            if (!is_file($path) || !is_readable($path)) {
                continue;
            }

            $filesize = (int) (filesize($path) ?: 0);
            $modified_at = (int) (filemtime($path) ?: 0);
            $url = $base_url . spiralist_encode_asset_url_path($filename);

            $files[] = [
                'path' => $path,
                'url' => $url,
                'filename' => $filename,
                'filesize' => $filesize,
                'modifiedAt' => $modified_at,
            ];
            $signature_parts[] = strtolower($base_path . '|' . $filename) . '|' . $filesize . '|' . $modified_at . '|' . $url;
        }
    }

    sort($signature_parts, SORT_STRING);

    $manifest_cache[$cache_key] = [
        'signature' => !empty($signature_parts) ? hash('sha256', implode("\n", $signature_parts)) : '',
        'files' => $files,
    ];

    return $manifest_cache[$cache_key];
}

function spiralist_get_image_asset_candidates(array $filenames): array
{
    $candidates = [];
    $seen = [];

    foreach ($filenames as $filename) {
        $basename = trim(basename((string) $filename));
        if ($basename === '') {
            continue;
        }

        $asset = spiralist_get_book_page_asset_by_filename($basename);
        if (empty($asset)) {
            continue;
        }

        $key = strtolower((string) ($asset['path'] ?? $basename));
        if (isset($seen[$key])) {
            continue;
        }

        $seen[$key] = true;
        $candidates[] = $asset;
    }

    return $candidates;
}

function spiralist_get_first_available_asset(array $candidates): array
{
    foreach ($candidates as $candidate) {
        $path = (string) ($candidate['path'] ?? '');
        if ($path !== '' && file_exists($path) && is_readable($path)) {
            return $candidate;
        }
    }

    return [];
}

function spiralist_get_site_image_url(array $filenames): string
{
    $asset = spiralist_get_first_available_asset(
        spiralist_get_image_asset_candidates($filenames)
    );

    return (string) ($asset['url'] ?? '');
}

function spiralist_get_public_image_variant_specs(): array
{
    return [
        'thumbnail' => [
            'max_width' => 360,
            'max_height' => 540,
        ],
        'large' => [
            'max_width' => 640,
            'max_height' => 960,
        ],
        'interactive' => [
            'max_width' => 2400,
            'max_height' => 3600,
        ],
    ];
}

function spiralist_get_public_image_variant_storage_root(): array
{
    $uploads = wp_get_upload_dir();
    $base_path = rtrim((string) ($uploads['basedir'] ?? ''), '/\\');
    $base_url = untrailingslashit((string) ($uploads['baseurl'] ?? ''));

    if ($base_path === '' || $base_url === '') {
        return [];
    }

    $path = $base_path . DIRECTORY_SEPARATOR . 'spiralist' . DIRECTORY_SEPARATOR . 'image-variants';
    $url = $base_url . '/spiralist/image-variants';

    if (!is_dir($path) && !wp_mkdir_p($path)) {
        return [];
    }

    return [
        'path' => $path,
        'url' => $url,
    ];
}

function spiralist_get_public_image_variant_location(array $asset, string $variant): array
{
    $root = spiralist_get_public_image_variant_storage_root();
    $source_path = trim((string) ($asset['path'] ?? ''));
    $source_filename = trim((string) ($asset['filename'] ?? basename($source_path)));
    $extension = strtolower((string) pathinfo($source_filename, PATHINFO_EXTENSION));

    if (empty($root) || $source_path === '' || $source_filename === '' || $extension === '') {
        return [];
    }

    $variant_path = rtrim((string) ($root['path'] ?? ''), '/\\') . DIRECTORY_SEPARATOR . $variant;
    $variant_url = untrailingslashit((string) ($root['url'] ?? '')) . '/' . rawurlencode($variant);

    if ($variant_path === '' || $variant_url === '') {
        return [];
    }

    if (!is_dir($variant_path) && !wp_mkdir_p($variant_path)) {
        return [];
    }

    $basename = sanitize_title((string) pathinfo($source_filename, PATHINFO_FILENAME));
    if ($basename === '') {
        $basename = 'image';
    }

    $signature = substr(
        md5(strtolower($source_filename) . '|' . (string) (@filesize($source_path) ?: 0)),
        0,
        12
    );
    $variant_filename = $basename . '-' . $signature . '.' . $extension;

    return [
        'path' => $variant_path . DIRECTORY_SEPARATOR . $variant_filename,
        'url' => $variant_url . '/' . rawurlencode($variant_filename),
        'filename' => $variant_filename,
    ];
}

function spiralist_generate_public_image_asset_variant(array $asset, string $variant): array
{
    static $cache = [];

    $normalized_variant = sanitize_key($variant);
    $source_path = trim((string) ($asset['path'] ?? ''));
    $source_url = trim((string) ($asset['url'] ?? ''));
    $source_filename = trim((string) ($asset['filename'] ?? basename($source_path)));
    $specs = spiralist_get_public_image_variant_specs();
    $original = [
        'path' => $source_path,
        'url' => $source_url,
        'filename' => $source_filename,
    ];

    if (
        $normalized_variant === ''
        || !isset($specs[$normalized_variant])
        || $source_path === ''
        || !is_file($source_path)
        || !is_readable($source_path)
    ) {
        return $original;
    }

    $cache_key = implode(
        '|',
        [
            $normalized_variant,
            strtolower(wp_normalize_path($source_path)),
            (string) (@filemtime($source_path) ?: 0),
            (string) (@filesize($source_path) ?: 0),
        ]
    );

    if (isset($cache[$cache_key])) {
        return $cache[$cache_key];
    }

    $location = spiralist_get_public_image_variant_location($asset, $normalized_variant);
    if (empty($location['path']) || empty($location['url'])) {
        $cache[$cache_key] = $original;

        return $cache[$cache_key];
    }

    $target_path = (string) $location['path'];
    $source_mtime = (int) (@filemtime($source_path) ?: 0);
    $target_mtime = (int) (@filemtime($target_path) ?: 0);

    if (is_file($target_path) && $target_mtime >= $source_mtime) {
        $cache[$cache_key] = $location;

        return $cache[$cache_key];
    }

    if (!function_exists('wp_get_image_editor')) {
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    if (!function_exists('wp_get_image_editor')) {
        $cache[$cache_key] = $original;

        return $cache[$cache_key];
    }

    $editor = wp_get_image_editor($source_path);
    if (is_wp_error($editor)) {
        $cache[$cache_key] = $original;

        return $cache[$cache_key];
    }

    $spec = $specs[$normalized_variant];
    $size = method_exists($editor, 'get_size') ? (array) $editor->get_size() : [];
    $width = (int) ($size['width'] ?? 0);
    $height = (int) ($size['height'] ?? 0);
    $copied = false;

    if ($width > 0 && $height > 0 && $width <= (int) $spec['max_width'] && $height <= (int) $spec['max_height']) {
        $copied = @copy($source_path, $target_path);
    } else {
        $resized = $editor->resize((int) $spec['max_width'], (int) $spec['max_height'], false);
        if (is_wp_error($resized)) {
            $cache[$cache_key] = $original;

            return $cache[$cache_key];
        }

        $saved = $editor->save($target_path);
        if (is_wp_error($saved) || empty($saved['path']) || !is_file((string) $saved['path'])) {
            $cache[$cache_key] = $original;

            return $cache[$cache_key];
        }
    }

    if ($copied && !is_file($target_path)) {
        $cache[$cache_key] = $original;

        return $cache[$cache_key];
    }

    @chmod($target_path, 0644);
    $cache[$cache_key] = $location;

    return $cache[$cache_key];
}