Skip to main content

Overview

The gallery system in Yoneily serves as both the product management system and a flexible multimedia content manager. It handles image uploads, automatic resizing, file attachments, and content organization.
In Yoneily, “Gallery” is the internal name for product listings. Each gallery item represents a product with images, descriptions, pricing, and inventory tracking.

Dual Purpose System

Product Listings

Primary use: E-commerce product catalog with pricing, stock, and sales tracking

Content Gallery

Secondary use: Multimedia content management for images, audio, and video

Image Management

Upload System

The gallery uses MeioUpload behavior for file handling: Configuration:
'MeioUpload' => array(
    'thumbnails' => array(
        'dir' => 'files{DS}galeria/otras',
        'create_directory' => true,
        'thumbnailQuality' => 50,
        'useImageMagick' => true
    )
)

Supported File Types

Formats: JPG, JPEG, PNG, GIFMIME Types:
  • image/gif
  • image/jpeg
  • image/pjpeg
  • image/png
Use Cases:
  • Product photos
  • Promotional banners
  • Gallery thumbnails
  • Content illustrations

Image Processing Pipeline

When an image is uploaded, Yoneily automatically generates three versions:
1

Original Storage

Location: /files/galeria/otras/Original uploaded file stored as-is for future processing
2

Thumbnail Generation

Location: /files/galeria/thumbnails/Dimensions: 124x124 (max)
$image = new SimpleImage();
$image->load($original_file_path);
if($image->getWidth() > 124){
    $image->resizeToWidth(124);
}
if($image->getHeight() > 124){
    $image->resizeToHeight(124);
}
$image->save($thumbnail_path);
3

Normal Display Version

Location: /files/galeria/normal/Dimensions: 600x480 (max)
$image = new SimpleImage();
$image->load($original_file_path);
if($image->getWidth() > 600){
    $image->resizeToWidth(600);
}
if($image->getHeight() > 480){
    $image->resizeToHeight(480);
}
$image->save($normal_path);

Image Size Reference

VersionDimensionsUse Case
OriginalAs uploadedSource file, archive
Thumbnail124x124 maxGrid views, listings, previews
Normal600x480 maxProduct detail pages, lightbox

Multiple Image Attachments

File Association System

Galleries support multiple images through the archivos (files) table: Join Table: archivos_galleries
CREATE TABLE archivos_galleries (
  files_id_file INT,
  galerias_id_galeria INT,
  PRIMARY KEY (files_id_file, galerias_id_galeria)
);

Archivos (Files) Structure

FieldTypeDescription
id_fileintUnique file identifier
nombre_filevarchar(45)Original filename
vidthumbnailvarchar(255)Video thumbnail path
embedthumbvarchar(255)Embedded thumbnail
nombre_galvarchar(255)Gallery display name
nombre_thumbvarchar(255)Thumbnail name
dirvarchar(255)Storage directory
fechacre_filetimestampUpload timestamp
mimetypevarchar(45)File MIME type
usuario_id_usuariointUploader user ID

Adding Multiple Images

1

Create/Edit Gallery

Navigate to gallery add or edit page
2

Upload Primary Image

Select main thumbnail image (required)
3

Attach Additional Files

Use file attachment interface to add more images:
  • Multiple product angles
  • Detail shots
  • Size comparisons
  • Usage examples
4

Save Gallery

System creates records in both galleries and archivos_galleries tables

Deleting Attached Images

Endpoint: /galleries/deleteimg/{gallery_id}/{file_id} SQL Query:
DELETE FROM archivos_galleries, archivos 
USING archivos_galleries 
INNER JOIN archivos ON archivos_galleries.files_id_file = archivos.id_file 
INNER JOIN galleries ON archivos_galleries.galerias_id_galeria = galleries.id_galeria 
WHERE galleries.id_galeria = $id 
AND archivos.id_file = $idfile
This operation permanently deletes file metadata from the database but does not remove physical files from the server.

Category Organization

Galleries use a many-to-many relationship with categories: Join Table: categories_galleries
'Category' => array(
    'className' => 'Category',
    'joinTable' => 'categories_galleries',
    'foreignKey' => 'galleries_id_galeria',
    'associationForeignKey' => 'categories_id_categorias',
    'unique' => true
)

Hierarchical Categories

Categories support parent-child relationships:
Category Model:
  belongsTo: ParentCategory
  hasMany: ChildCategory
Example Structure:
Furniture
├── Living Room
│   ├── Sofas
│   └── Coffee Tables
├── Bedroom
│   ├── Beds
│   └── Dressers
└── Outdoor
    ├── Patio Sets
    └── Garden Chairs

Category Fields

FieldDescription
id_categoriasCategory identifier
nombre_categoriasCategory name (display field)
categorias_id_categoriasParent category ID (for subcategories)
usuario_id_usuarioCreator user ID

URL System

SEO-Friendly URLs

Galleries automatically generate clean URLs: Generation Logic:
$currentUrl = Inflector::slug(strtolower($this->data['Gallery']['texto_galeria']));
$claves = Inflector::slug(strtolower($this->data['Gallery']['claves']));
$url = $currentUrl . $claves;
Example:
  • Title: “Mesa de Madera Artesanal”
  • Keywords: “roble artesania”
  • URL: mesa-de-madera-artesanal-roble-artesania

Duplicate URL Handling

The beforeSave() method ensures URL uniqueness:
$result = $this->find('all', array(
    'conditions' => array(
        'Gallery.url' => $currentUrl . $claves,
        'Gallery.id_galeria !=' => $this->id
    ),
    'fields' => array('Gallery.*')
));

Visibility Control

Publication Status

Published (publicar = 1)

Gallery is visible on public-facing siteActivate: /galleries/activa/{id}

Hidden (publicar = 0)

Gallery is hidden from public viewDeactivate: /galleries/desactiva/{id}

Exclusion Flag

Field: excluir (tinyint) Values:
  • 0 - Include in listings
  • 1 - Exclude from certain views
Use Cases:
  • Featured content filtering
  • Special collections
  • Internal-only galleries

Store Association

Vendor Filtering

Vendors see only their own galleries:
$user = $this->Session->read('Auth.User.locale_id_local');
if(!empty($user)){
    $this->paginate = array(
        'conditions' => array('Gallery.locale_id_local' => $user),
        'limit' => 10,
        'order' => 'fechacre_galeria DESC'
    );
}

Store Autocomplete

Endpoint: /galleries/verlocal Request:
{ "term": "arte" }
Response:
[
  {
    "id": 1,
    "value": "El Punto Artesanal de Magdaleno"
  }
]
Implementation:
$locales = $this->Locale->find('all', array(
    'fields' => array('Locale.nombre_empresa', 'Locale.id_local'),
    'conditions' => array(
        'Locale.nombre_empresa LIKE' => '%' . $frase . '%',
        'Locale.status =' => 1
    )
));

Pagination Settings

Default Configuration:
$this->paginate = array(
    'limit' => 10,
    'order' => 'fechacre_galeria DESC'
);
Features:
  • 10 galleries per page
  • Newest galleries first
  • Related data loaded:
    • User information
    • Store/locale details
    • Categories
    • Attached files

Listing View Elements

For each gallery, display:
  • Thumbnail image (124x124)
  • Product/content name
  • Price (if product)
  • Store/vendor name
  • Publication status (published/hidden)
  • Stock level indicator
  • Exclusion status
  • Creation date
  • Edit gallery
  • Delete gallery
  • Activate/Deactivate
  • View details
  • Manage images

Technical Implementation

SimpleImage Class

Yoneily uses a custom image manipulation class: Location: app/vendors/SimpleImage.php Key Methods:
  • load($filename) - Load image from file
  • getWidth() - Get image width
  • getHeight() - Get image height
  • resizeToWidth($width) - Resize maintaining aspect ratio
  • resizeToHeight($height) - Resize maintaining aspect ratio
  • save($filename, $quality) - Save processed image
Usage:
App::import('Vendor', 'convertidor', array('file' => 'SimpleImage.php'));

$image = new SimpleImage();
$image->load($original_file_path);
if($image->getWidth() > 600){
    $image->resizeToWidth(600);
}
$image->save($normal_path);

Model Validation

var $validate = array(
    'texto_galeria' => array(
        'rule' => array('notEmpty'),
        'message' => 'No debes dejar vacio el campo'
    ),
    'claves' => array(
        'rule' => array('notEmpty'),
        'message' => 'No debes dejar vacio el campo'
    ),
    'descripcion' => array(
        'rule' => array('notEmpty'),
        'message' => 'No debes dejar vacio el campo'
    ),
    'locale_id_local' => array(
        'rule' => array('notEmpty'),
        'message' => '* Requerido'
    )
);

Best Practices

  • Upload high-quality source images
  • Let the system handle resizing
  • Use JPG for photos, PNG for graphics
  • Optimize originals before upload (reasonable file size)
  • Add images from different angles
  • Include detail shots
  • Show products in use context
  • Limit to 5-10 images per gallery
  • Use descriptive titles
  • Add comprehensive keywords
  • Assign appropriate categories
  • Write detailed descriptions
  • Periodically clean unused images
  • Monitor disk space usage
  • Archive old galleries instead of deleting
  • Backup image directories regularly

Inventory Management

Product catalog and stock

Promotions

Promotional galleries

User Management

Vendor access control

File System Structure

app/webroot/files/
├── galeria/
│   ├── otras/          # Original uploads
│   ├── thumbnails/     # 124x124 thumbnails
│   └── normal/         # 600x480 display images
├── promos/
│   ├── otras/          # Original promo images
│   ├── thumbnails/     # 450x280 thumbnails
│   └── slider/         # 779x280 slider images
└── videothumbnail/     # Video thumbnails
Ensure web server has write permissions to these directories for image processing to function correctly.

Build docs developers (and LLMs) love