WYSIWYG Image Synchronization for CMS Content in OpenMage Image Cleaner

OpenMage Image Cleaner identifies orphaned WYSIWYG assets by scanning the media/wysiwyg directory and cross-referencing every file against HTML content from CMS pages, static blocks, and email templates, plus all frontend CSS files, then persists unused images to a module-specific database table for safe removal.

The OpenMage Image Cleaner extension provides a robust mechanism to prevent media bloat by detecting unused assets across the platform. Its WYSIWYG image synchronization feature specifically targets images uploaded through the WYSIWYG editor, ensuring that only truly orphaned files—those no longer referenced by any CMS content, email template, or stylesheet—are flagged for deletion.

Entry Point and Controller Architecture

The synchronization process initiates via the admin UI route that resolves to FbimagecleanerController::syncwysiwygAction() in app/code/community/Fballiano/ImageCleaner/controllers/Adminhtml/FbimagecleanerController.php (starting at line 163).

The controller prepares the execution environment by setting entity_type_id = -98, a hardcoded internal identifier that categorizes WYSIWYG assets distinctly from product or category images. It then resolves the physical directory path to media/wysiwyg and loads the module helper and Magento core resources.

Aggregating Content References

Database HTML Content

At line 177, the controller executes a single SQL query that unions content columns from three core Magento tables to capture all potential image references:

  • cms_page.content – HTML bodies of CMS pages
  • cms_block.content – HTML content of static blocks
  • core_email_template.template_text and core_email_template.template_styles – Email template bodies and inline styles

The result set ($db_images) contains every HTML fragment stored in the CMS and email system that may contain WYSIWYG image URLs.

CSS Stylesheet Content

Beyond database content, the synchronization captures image references embedded in stylesheets. The controller calls $helper->getAllCSSFilesContents(), implemented in app/code/community/Fballiano/ImageCleaner/Helper/Data.php at lines 46-55.

This helper method recursively traverses the skin/frontend directory structure, identifies all *.css files, reads their contents into memory, and returns them as an array of strings. This ensures that background images and other CSS-referenced assets are accounted for in the usage analysis.

Filesystem Enumeration and Usage Detection

Scanning Physical Assets

Using the helper’s scandirRecursive() method, the controller performs a recursive directory scan of media/wysiwyg. It strips the base media path so every entry is relative to the wysiwyg/ directory, producing the complete inventory of physical assets ($fs_images).

Determining Used Images

The core logic employs a three-tier validation process to classify images as used:

  1. Swatch Exclusion: If system configuration configswatches/general/enabled is active, any image matching the pattern wysiwyg/swatches/* is automatically marked as used, preventing the deletion of product color swatches.

  2. HTML Content Matching: For each filesystem image, the controller performs case-insensitive substring searches (stripos()) against every entry in the aggregated HTML content from CMS pages, blocks, and email templates.

  3. CSS Content Matching: Similarly, each CSS file string is searched via stripos() for the image filename.

Images that fail all three checks are collected via array_diff($fs_images, $used_images) and classified as unused.

Persisting Results to Database

The final stage stores orphaned assets in the module’s fb_imagecleaner_image table. The controller strips the wysiwyg/ prefix from each unused path and executes an INSERT IGNORE query (lines 200-215 in the controller), recording the relative path with entity_type_id = -98.

This idempotent insertion prevents duplicate entries if the synchronization runs multiple times. After processing, the controller redirects to the admin grid where the new unused WYSIWYG entries are displayed for deletion or export.

Triggering Synchronization via Admin URL

Administrators initiate the scan through the backend interface. The action URL resolves to:

// Admin route triggering the WYSIWYG sync
Mage::helper('adminhtml')->getUrl('adminhtml/fbimagecleaner/syncwysiwyg');

Accessing this endpoint executes the complete workflow and redirects to the image cleaner grid, displaying newly identified unused WYSIWYG assets alongside other entity types.

Summary

  • WYSIWYG image synchronization identifies orphaned media by comparing physical files in media/wysiwyg against database content and CSS references from the entire frontend skin directory.
  • The process initiates via syncwysiwygAction() in FbimagecleanerController.php, utilizing entity_type_id = -98 to categorize WYSIWYG assets distinctly from product or category images.
  • Database scanning aggregates HTML from cms_page, cms_block, and core_email_template tables via a single UNION query to capture all potential image references.
  • CSS analysis recursively loads all stylesheets from skin/frontend to detect background images and other stylesheet-referenced assets.
  • Usage determination employs case-insensitive substring matching (stripos()) against HTML and CSS content, with automatic exclusion for product swatches in wysiwyg/swatches/.
  • Unused images are persisted to fb_imagecleaner_image via INSERT IGNORE to prevent duplicates, enabling safe bulk deletion through the admin interface.

Frequently Asked Questions

How does the synchronization distinguish between used and unused WYSIWYG images?

The system employs a three-tier validation process. First, it checks if the image resides in the wysiwyg/swatches/ directory and if product color swatches are enabled in system configuration; these are automatically preserved. For all other images, it performs case-insensitive substring searches (stripos()) against the aggregated HTML content from CMS pages, blocks, and email templates, as well as the contents of all CSS files in the frontend skin directory. Images absent from all these sources are classified as unused.

Which database tables are scanned during WYSIWYG synchronization?

The synchronization queries union the content columns from three core Magento tables: cms_page (specifically the content column), cms_block (the content column), and core_email_template (both the template_text and template_styles columns). This comprehensive scan ensures that image references embedded in page content, static blocks, and transactional email templates are all captured for cross-referencing against the filesystem.

What is the purpose of the entity_type_id = -98 value used in the code?

The value -98 serves as a hardcoded internal identifier within the OpenMage Image Cleaner module to categorize WYSIWYG assets distinctly from other entity types such as product images or category images. This constant allows the controller, helper methods, and database insertion logic to consistently reference and filter WYSIWYG-specific records when storing unused images in the fb_imagecleaner_image table or displaying them in the admin grid.

How are CSS files included in the usage analysis?

The helper class located at app/code/community/Fballiano/ImageCleaner/Helper/Data.php provides the getAllCSSFilesContents() method, which recursively traverses the skin/frontend directory structure. It identifies all files with the .css extension, reads their contents into memory, and returns them as an array of strings. During synchronization, the controller searches these CSS strings for image filenames using case-insensitive substring matching, ensuring that background images and other stylesheet-referenced assets are not mistakenly flagged as unused.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →