diff --git a/.htaccess b/.htaccess index e2bbc23..12fa816 100644 --- a/.htaccess +++ b/.htaccess @@ -2,17 +2,18 @@ DirectoryIndex index.php index.html Options -Indexes Options -MultiViews +# BEGIN WordPress +# The directives (lines) between "BEGIN WordPress" and "END WordPress" are +# dynamically generated, and should only be modified via WordPress filters. +# Any changes to the directives between these markers will be overwritten. + RewriteEngine On - -# 0) Serve existing files/directories as-is -RewriteCond %{REQUEST_FILENAME} -f [OR] -RewriteCond %{REQUEST_FILENAME} -d -RewriteRule ^ - [L] - -# 1) Internal map: /page or /page/ -> /page.php (if such PHP file exists) -RewriteCond %{REQUEST_FILENAME}.php -f -RewriteRule ^(.+?)/?$ $1.php [L] - -# 2) Optional: strip trailing slash for non-directories (keeps .php links working) +RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] +RewriteBase / +RewriteRule ^index\.php$ - [L] +RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ^(.+)/$ $1 [R=301,L] +RewriteRule . /index.php [L] + + +# END WordPress \ No newline at end of file diff --git a/admin_credentials.txt b/admin_credentials.txt index d888f1b..7c79fc2 100644 --- a/admin_credentials.txt +++ b/admin_credentials.txt @@ -1,4 +1,4 @@ WordPress Admin Credentials: URL: http://localhost/wp-admin Username: admin -Password: c59u3v2geHuIQMRP +Password: DA3st8vOerHPJqyhHy diff --git a/wp-content/plugins/smart-image-resizer/assets/admin.css b/wp-content/plugins/smart-image-resizer/assets/admin.css new file mode 100644 index 0000000..e4bfb4d --- /dev/null +++ b/wp-content/plugins/smart-image-resizer/assets/admin.css @@ -0,0 +1 @@ +.sir-wrap{--sir-primary:#2563eb;--sir-ink:#0f172a;--sir-muted:#64748b;--sir-surface:#fff;--sir-soft:#eff6ff}.sir-hero{display:flex;justify-content:space-between;gap:28px;align-items:center;margin:22px 0;padding:32px;border-radius:24px;background:linear-gradient(135deg,#0f172a,#1d4ed8 58%,#38bdf8);color:#fff;box-shadow:0 22px 55px rgba(15,23,42,.18)}.sir-hero h1{font-size:42px;line-height:1;margin:0 0 12px}.sir-hero p{font-size:16px;max-width:760px;margin:0;color:#dbeafe}.sir-kicker{letter-spacing:.14em;text-transform:uppercase;font-size:12px!important;font-weight:700;color:#bfdbfe!important;margin-bottom:10px!important}.sir-stats{background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.24);border-radius:20px;padding:22px 28px;text-align:center;min-width:140px}.sir-stats strong{display:block;font-size:42px;line-height:1}.sir-stats span{color:#e0f2fe}.sir-grid{display:grid;grid-template-columns:minmax(0,1.6fr) minmax(300px,.8fr);gap:20px}.sir-card{background:#fff;border:1px solid #dbe3ef;border-radius:18px;padding:24px;box-shadow:0 10px 30px rgba(15,23,42,.06)}.sir-card-wide{grid-row:span 2}.sir-card h2{margin-top:0;color:var(--sir-ink);font-size:22px}.sir-table input[type=text],.sir-table input[type=number],.sir-table input:not([type]){width:100%;max-width:180px}.sir-toggle{display:block;margin:14px 0;font-weight:600}.sir-safe{background:#ecfdf5;border:1px solid #bbf7d0;color:#166534;border-radius:12px;padding:12px 14px}.sir-card select,.sir-card input[type=number]{width:100%;margin:8px 0 16px}.sir-log{margin:0}.sir-log li{padding:12px 0;border-bottom:1px solid #eef2f7}.sir-log strong{display:block;color:#0f172a}.sir-log span{color:#64748b}@media(max-width:960px){.sir-grid,.sir-hero{display:block}.sir-stats{margin-top:20px}.sir-hero h1{font-size:34px}} diff --git a/wp-content/plugins/smart-image-resizer/smart-image-resizer.php b/wp-content/plugins/smart-image-resizer/smart-image-resizer.php new file mode 100644 index 0000000..2fd1efb --- /dev/null +++ b/wp-content/plugins/smart-image-resizer/smart-image-resizer.php @@ -0,0 +1,337 @@ +default_settings()); + } + } + + public function default_settings(): array { + return [ + 'auto_resize' => 1, + 'webp' => 0, + 'keep_original' => 1, + 'presets' => [ + ['name' => 'Card Thumbnail', 'slug' => 'card-thumb', 'width' => 480, 'height' => 320, 'crop' => 1], + ['name' => 'Content Medium', 'slug' => 'content-medium', 'width' => 960, 'height' => 0, 'crop' => 0], + ['name' => 'Hero Banner', 'slug' => 'hero-banner', 'width' => 1600, 'height' => 900, 'crop' => 1], + ['name' => 'Square Social', 'slug' => 'square-social', 'width' => 1080, 'height' => 1080, 'crop' => 1], + ], + ]; + } + + public function get_settings(): array { + $settings = get_option(self::OPTION, []); + return wp_parse_args(is_array($settings) ? $settings : [], $this->default_settings()); + } + + public function admin_menu(): void { + add_media_page( + __('Smart Image Resizer', 'smart-image-resizer'), + __('Image Resizer', 'smart-image-resizer'), + 'upload_files', + 'smart-image-resizer', + [$this, 'render_admin_page'] + ); + } + + public function admin_assets(string $hook): void { + if ($hook !== 'media_page_smart-image-resizer') { + return; + } + wp_enqueue_style('sir-admin', plugin_dir_url(__FILE__) . 'assets/admin.css', [], '0.1.0'); + } + + public function handle_admin_actions(): void { + if (!is_admin() || empty($_POST['sir_action'])) { + return; + } + if (!current_user_can('upload_files')) { + wp_die(esc_html__('You do not have permission to resize images.', 'smart-image-resizer')); + } + check_admin_referer(self::NONCE_ACTION); + $action = sanitize_key($_POST['sir_action']); + + if ($action === 'save_settings') { + $this->save_settings_from_post(); + wp_safe_redirect(add_query_arg(['page' => 'smart-image-resizer', 'sir_notice' => 'settings_saved'], admin_url('upload.php'))); + exit; + } + + if ($action === 'bulk_resize') { + $preset_slug = sanitize_title(wp_unslash($_POST['preset_slug'] ?? '')); + $limit = max(1, min(50, absint($_POST['limit'] ?? 20))); + $result = $this->bulk_resize($preset_slug, $limit); + set_transient('sir_last_bulk_result_' . get_current_user_id(), $result, MINUTE_IN_SECONDS * 5); + wp_safe_redirect(add_query_arg(['page' => 'smart-image-resizer', 'sir_notice' => 'bulk_done'], admin_url('upload.php'))); + exit; + } + } + + private function save_settings_from_post(): void { + $presets = []; + $names = array_map('sanitize_text_field', wp_unslash($_POST['preset_name'] ?? [])); + $slugs = array_map('sanitize_title', wp_unslash($_POST['preset_slug'] ?? [])); + $widths = array_map('absint', wp_unslash($_POST['preset_width'] ?? [])); + $heights = array_map('absint', wp_unslash($_POST['preset_height'] ?? [])); + $crops = isset($_POST['preset_crop']) ? array_map('absint', wp_unslash($_POST['preset_crop'])) : []; + + for ($i = 0; $i < 6; $i++) { + $name = trim($names[$i] ?? ''); + $slug = sanitize_title($slugs[$i] ?? $name); + $width = $widths[$i] ?? 0; + $height = $heights[$i] ?? 0; + if (!$name || !$slug || $width < 1) { + continue; + } + $presets[] = [ + 'name' => $name, + 'slug' => $slug, + 'width' => $width, + 'height' => $height, + 'crop' => !empty($crops[$i]) ? 1 : 0, + ]; + } + if (!$presets) { + $presets = $this->default_settings()['presets']; + } + + update_option(self::OPTION, [ + 'auto_resize' => !empty($_POST['auto_resize']) ? 1 : 0, + 'webp' => !empty($_POST['webp']) ? 1 : 0, + 'keep_original' => 1, + 'presets' => $presets, + ]); + } + + public function render_admin_page(): void { + $settings = $this->get_settings(); + $presets = array_values($settings['presets']); + $notice = sanitize_key($_GET['sir_notice'] ?? ''); + $last = get_transient('sir_last_bulk_result_' . get_current_user_id()); + ?> +
+
+
+

+

+

+
+
+ + +
+
+ + +

+ + +

+ + +
+
+ + +

+

+ + + + '','slug'=>'','width'=>'','height'=>'','crop'=>0]; ?> + + + + + + + + + +
NameSlugWidthHeightCrop
+ +

+ + +

+ +
+ +
+

+

+
+ + + + + + + +
+
+ +
+

+ render_logs(); ?> +
+
+
+ ' . esc_html__('No resize jobs yet. Upload an image or run a bulk job to see activity here.', 'smart-image-resizer') . '

'; + return; + } + echo ''; + } + + public function resize_on_upload(int $attachment_id): void { + $settings = $this->get_settings(); + if (empty($settings['auto_resize']) || !wp_attachment_is_image($attachment_id)) { + return; + } + foreach ($settings['presets'] as $preset) { + $this->resize_attachment($attachment_id, $preset, !empty($settings['webp'])); + } + } + + public function bulk_resize(string $preset_slug, int $limit): array { + $settings = $this->get_settings(); + $preset = null; + foreach ($settings['presets'] as $candidate) { + if ($candidate['slug'] === $preset_slug) { + $preset = $candidate; + break; + } + } + if (!$preset) { + return ['resized' => 0, 'skipped' => 0, 'errors' => 1]; + } + $ids = get_posts([ + 'post_type' => 'attachment', + 'post_mime_type' => 'image', + 'post_status' => 'inherit', + 'posts_per_page' => $limit, + 'fields' => 'ids', + 'orderby' => 'date', + 'order' => 'DESC', + ]); + $result = ['resized' => 0, 'skipped' => 0, 'errors' => 0]; + foreach ($ids as $id) { + $status = $this->resize_attachment((int) $id, $preset, !empty($settings['webp'])); + if ($status === true) { + $result['resized']++; + } elseif ($status === 'exists') { + $result['skipped']++; + } else { + $result['errors']++; + } + } + return $result; + } + + private function resize_attachment(int $attachment_id, array $preset, bool $make_webp = false) { + $file = get_attached_file($attachment_id); + if (!$file || !file_exists($file)) { + return false; + } + $editor = wp_get_image_editor($file); + if (is_wp_error($editor)) { + return false; + } + $info = pathinfo($file); + $slug = sanitize_title($preset['slug']); + $width = absint($preset['width']); + $height = absint($preset['height']); + $dest = trailingslashit($info['dirname']) . $info['filename'] . '-' . $slug . '-' . $width . 'x' . ($height ?: 'auto') . '.' . strtolower($info['extension']); + $existing = get_post_meta($attachment_id, self::META_KEY, true); + $existing = is_array($existing) ? $existing : []; + if (file_exists($dest)) { + return 'exists'; + } + $resized = $editor->resize($width, $height ?: null, !empty($preset['crop'])); + if (is_wp_error($resized)) { + return false; + } + $saved = $editor->save($dest); + if (is_wp_error($saved) || empty($saved['path'])) { + return false; + } + $existing[$slug] = [ + 'path' => $saved['path'], + 'file' => wp_basename($saved['path']), + 'width' => $saved['width'] ?? $width, + 'height' => $saved['height'] ?? $height, + 'created' => current_time('mysql'), + ]; + if ($make_webp && function_exists('imagewebp')) { + $webp_editor = wp_get_image_editor($saved['path']); + if (!is_wp_error($webp_editor)) { + $webp_dest = preg_replace('/\.[^.]+$/', '.webp', $saved['path']); + $webp_saved = $webp_editor->save($webp_dest, 'image/webp'); + if (!is_wp_error($webp_saved) && !empty($webp_saved['path'])) { + $existing[$slug]['webp'] = wp_basename($webp_saved['path']); + } + } + } + update_post_meta($attachment_id, self::META_KEY, $existing); + $this->add_log(get_the_title($attachment_id), sprintf('Created %s at %sx%s', $preset['name'], $existing[$slug]['width'], $existing[$slug]['height'])); + return true; + } + + private function add_log(string $title, string $message): void { + $logs = get_option(self::LOG_OPTION, []); + $logs[] = ['time' => current_time('mysql'), 'title' => $title ?: 'Untitled image', 'message' => $message]; + update_option(self::LOG_OPTION, array_slice($logs, -30)); + } +} + +Smart_Image_Resizer::instance(); diff --git a/wp-content/uploads/2026/06/sir-test-source-1024x683.jpg b/wp-content/uploads/2026/06/sir-test-source-1024x683.jpg new file mode 100644 index 0000000..d916ca9 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-1024x683.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source-150x150.jpg b/wp-content/uploads/2026/06/sir-test-source-150x150.jpg new file mode 100644 index 0000000..0e63e55 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-150x150.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source-300x200.jpg b/wp-content/uploads/2026/06/sir-test-source-300x200.jpg new file mode 100644 index 0000000..8513505 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-300x200.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source-768x512.jpg b/wp-content/uploads/2026/06/sir-test-source-768x512.jpg new file mode 100644 index 0000000..feac6fa Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-768x512.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source-card-thumb-480x320.jpg b/wp-content/uploads/2026/06/sir-test-source-card-thumb-480x320.jpg new file mode 100644 index 0000000..709e410 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-card-thumb-480x320.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source-content-medium-960xauto.jpg b/wp-content/uploads/2026/06/sir-test-source-content-medium-960xauto.jpg new file mode 100644 index 0000000..5c2eba6 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-content-medium-960xauto.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source-square-social-1080x1080.jpg b/wp-content/uploads/2026/06/sir-test-source-square-social-1080x1080.jpg new file mode 100644 index 0000000..0d61392 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source-square-social-1080x1080.jpg differ diff --git a/wp-content/uploads/2026/06/sir-test-source.jpg b/wp-content/uploads/2026/06/sir-test-source.jpg new file mode 100644 index 0000000..fde2575 Binary files /dev/null and b/wp-content/uploads/2026/06/sir-test-source.jpg differ diff --git a/wp-content/uploads/sir-test-source.jpg b/wp-content/uploads/sir-test-source.jpg new file mode 100644 index 0000000..fde2575 Binary files /dev/null and b/wp-content/uploads/sir-test-source.jpg differ diff --git a/wp-content/uploads/smart-image-resizer-0.1.0.zip b/wp-content/uploads/smart-image-resizer-0.1.0.zip new file mode 100644 index 0000000..0b2e08c Binary files /dev/null and b/wp-content/uploads/smart-image-resizer-0.1.0.zip differ