News:

Support the VirtueMart project and become a member

Main Menu

Why the weird Unique Filenames?

Started by neo314, November 29, 2012, 22:03:49 PM

Previous topic - Next topic

neo314

It is a minor annoyance, but why does the Unique Filename for a product's image, which I understand is actually an alias, come up with such weird names? I would expect it to do a simple increment or append the record id, but it seems to change the file name from mypic.jpg to mypic.jpg_produc and even mypic.jpg_produc_product. Any idea what is up with that?

bytelord

Production: Joomla 2.5.8 | VM 2.0.14 | PHP 5.3.13
Testing     : Joomla 2.5.8 | VM 2.0.16 | PHP 5.3.8
Testing     : Joomla 2.5.8 |    VM 2.1   | PHP 5.3.8

- Don't Forget to mark thread as solved when it is solved!
- Please do not PM with support questions, use the forum!

neo314

Quote from: bytelord on November 29, 2012, 22:27:50 PM
http://forum.virtuemart.net/index.php?topic=110591.msg370805#msg370805

Thanks for the reference, but my question was why the alias is made unique this way and, I guess, I was looking for whether anyone had managed to change it. Incrementing the file alias with a integer or the record id would be better than having to change it every time when many products share the same image. Incrementing or using the record id could be left alone, but myimage.jpg_product_product_product just looks stupid and is a waste, a small one, but still a waste of storage space.

neo314

#3
I'm also realizing that the rules for this alias are not necessarily clear. Initially I thought the alias had to be unique to the product, but apparently it is unique to the file.

So what is happening to me is that I have a product with 3 child products that has some custom fields I do not want to recreate. I clone the parent product. Open it and change the name, SKU, and save/upload the new image. Then when the product refreshes, I delete the image from the previous product leaving only the new image, BUT instead of the alias changing to the new image it tags _product onto the old image file name to make the alias.

I have not yet tried doing this in one step yet, but if I delete the image from the product, save/refresh, and then upload the new image I don't end up with the ugly alias.

[UPDATE: It does not work in one step. If I delete the image and apply the upload in one step I get the ugly alias, so delete the image => save => upload/save. Good alias.]

bytelord

Hello again,

When creating a product the following must be unique:
-Product Alias (else the sef urls will have issues - same url) - unique for the product

When a new media file created the following should be the unique:
-Unique filename :is a unique title for the media file

When you clone a product the product alias changed but the media filename is still the same because the same image is selected, when you upload a photo keeps the unique filename because already have a "value" and that because is "editable" because some people need custom file names on that for seo purposes. It adds a _product because is a product image, could be an auto increasing number that if you have 1-2000 medias each time have to scan how many images exists, remove the sequence ... count them ... place a new incresment number, etc ... that will affect the shop performance.

I forget my self a lot of times to change the unique file name (media title). May be a featured option allow to lock the unique filename have the same name with the image you upload.
Also keep in mind that people have images like ssg0011ffd2.jpg for example because are receiving those images from manufactures catalogs and import them to vm2 and they need to place a custom title for the images.
The best option is when upload a new media copy-paste the filename inside the unique filename.

Some of my clients for example uses SKU for product media filename and some other custom one's.

Regards
Production: Joomla 2.5.8 | VM 2.0.14 | PHP 5.3.13
Testing     : Joomla 2.5.8 | VM 2.0.16 | PHP 5.3.8
Testing     : Joomla 2.5.8 |    VM 2.1   | PHP 5.3.8

- Don't Forget to mark thread as solved when it is solved!
- Please do not PM with support questions, use the forum!

neo314

Well, I'm getting that. It is not obvious. It is a bit convoluted. I've got it working for me now, as I noted above, but what I am still a little fuzzy on is this...

When I upload the second image, doesn't there need to be an alias for each image? So why when I upload 2 additional images, they both have an alias of first_image.jpg_product? They should be different, and why do that at all when each image has a unique file name.

It seems to me the default alias should always be the image's file name and VM can offer an option to assign a different or formulaic alias (formulaic like [SKU]_[increment].[ext] or something). Appending _product to the first image's file name offers no advantage over using the uploaded image's file name, does it? If it does, I sure don't see it.

bytelord

#6
Hi,

Is because the vm tries to keep "alive" that information from the cloned product, also the media title must be unique. I will have a look on the source of media model and may be propose something for that. The incremental number is not an option because will affect performance on big shops (with 100k products for example).

Remind me if i forget it ...

Regards
Production: Joomla 2.5.8 | VM 2.0.14 | PHP 5.3.13
Testing     : Joomla 2.5.8 | VM 2.0.16 | PHP 5.3.8
Testing     : Joomla 2.5.8 |    VM 2.1   | PHP 5.3.8

- Don't Forget to mark thread as solved when it is solved!
- Please do not PM with support questions, use the forum!

neo314

Thanks for looking. I have a work flow now that solves my issue.

I would think the file name would be unique if the source folder is always the same. I am also not sure why incrementing would be a big performance hit. I understand the concept, but doesn't it check for uniqueness already? That is how you get myimage.jpg_product_product...? To do that, I would think it would add _product and test again and if that was not unique, try _product_product, and so on. So how is that different from trying myimage.jpg_1 and if that is not unique, try myimage.jpg_2 and so on?

I'm also not sure what you mean by, "vm tries to keep "alive" that information from the cloned product..." I realized that the cloning does not change the alias of the image. It comes from adding additional images to the product. If I want the alias to be related to the product, I should name my files that way (e.g. widget_view_1.jpg, widget_view_2.jpg, etc.), so choosing the file name as the alias seems to make more sense since the file name has to be unique (assuming the same source folder) and the name should be as descriptive as I want it to be. I do think the ability to apply an alias is great, but I think the implementation here has a minor issue.

bytelord

Hello,

Yes but this is not so easy ... what if the real file name of a product image is testimage_33 ... and find that this image is exist ... so will take the number _34??
For that reason i am trying to explain file_title is related to media type (product, category, etc) and also to file_name.

I check the media helper and model, i check also the media handler to figure out and make some tests ... but placing an incremental number is not easy and also is related to the folder that store as you mention, the function is places the an '_' + the last folder name. Also there is a possibility is the file_title from another product has the name _2 or _3 or whatever you will have duplicate entries, also at the moment you save your changes the file_name is empty because you are not uploading a new one.

What i can suggest is each time place a '_' and also a random number each time without the product (each time will place an _[random_number]
like myphoto_1_3_9_2 each time you clone it....

i make a lot of tests atm do that:
go in administrator\components\com_virtuemart\tables\medias.php and comment the lines 163,164 ... so the second if will run ... like it runs when your are working under stories/virtuemart

if (!empty($unique_id)) {
foreach ($unique_id as $item) {
if ($item['virtuemart_media_id'] != $this->virtuemart_media_id) {
//$lastDir = substr ($this->file_url, 0, strrpos ($this->file_url, '/'));
//$lastDir = substr ($lastDir, strrpos ($lastDir, '/') + 1);
if (!empty($lastDir)) {
$this->file_title = $this->file_title . '_' . $lastDir;
}
else {
$this->file_title = $this->file_title . '_' . rand (1, 9);
}
}
}
}


Regards
Production: Joomla 2.5.8 | VM 2.0.14 | PHP 5.3.13
Testing     : Joomla 2.5.8 | VM 2.0.16 | PHP 5.3.8
Testing     : Joomla 2.5.8 |    VM 2.1   | PHP 5.3.8

- Don't Forget to mark thread as solved when it is solved!
- Please do not PM with support questions, use the forum!

neo314

Hi bytelord,

I'll look at the code later, but looking at your explanation, I have a couple of observations. I have not entirely certain what the role of the alias is at the moment since I corrected all the ones I had in this store, however, I have done this many times for file uploads without overwrite. If the image's name is testimage_33 than the first increment is testimage_33_1. The fact that the name has a _ followed by a number does not mean that would be changed in the name. It is a simple process to separate the name from the file extension.

So yes, ideally, if testimage_33.jpg exists, the name would be changed to testimage_33_1.jpg and tested again. All of the images are, as far as I have seen, been uploaded to the same folder. I would suggest you don't need random numbers either. If testimage_33.jpg is the first image for this product, you could name it testimage_33_[productID]_1.jpg, and the second image test2_[productID]_2.jpg, but none of this is really necessary if the image file name is unique.

When you say, "Also there is a possibility is the file_title from another product has the name _2 or _3 or whatever you will have duplicate entries," but isn't it true that, since the alias is the same when I reuse an image on a different product, that the routine to test for uniqueness is checking all the media regardless of which product I am working on, so if I have some odd issue that is causing me to upload different images with the same file name, if myimage.jpg is used and myimage_1.jpg and myimage_2.jpg is used by other products, than this one would be myimage_3.jpg. If that does not suffice, tag every image with the product id and increment only against the product's images.

Again, my further checking indicated it was not cloning that was doing this (same image and same image alias), it was adding a second image to the product.

bytelord

Hello,

You can work in administrator\components\com_virtuemart\tables\medias.php and make the changes as you wish. If you have time to make some tests also will be nice. If you find a proper solution on that will be nice to share.

Suggest to work from line 144-178

Regards
Production: Joomla 2.5.8 | VM 2.0.14 | PHP 5.3.13
Testing     : Joomla 2.5.8 | VM 2.0.16 | PHP 5.3.8
Testing     : Joomla 2.5.8 |    VM 2.1   | PHP 5.3.8

- Don't Forget to mark thread as solved when it is solved!
- Please do not PM with support questions, use the forum!

neo314

Quote from: bytelord on November 30, 2012, 23:29:30 PM
Hello,

You can work in administrator\components\com_virtuemart\tables\medias.php and make the changes as you wish. If you have time to make some tests also will be nice. If you find a proper solution on that will be nice to share.

Suggest to work from line 144-178

Regards

I can try and do that. I am still very early in being familiar with the VM code. It appears that the problem occurs earlier in the process.
WARNING: I am not sure I am going to leave this hack in the file at this point because I am not sure about implications to other processes that may use this same code.

It appears that when the second or later image file is added to the product, medias.php is executed where $this->file_title is not empty and $this->file_name is empty. I discovered that $this->file_title is populated with the current value of the administrator product page's current value of Unique Filename, so if I click on the info of a second or third image that has a completely different "Unique Filename" than the first image, that previous Unique Filename is what gets the appended _product. In other words if the product has myimage.jpg and a second image with an alias of xyz, and I click on the information icon for xyz and then upload a new image, the third images alias would be xyz_product.

If the file_title were empty at this point, and the file_name held the file names value, the code at line 143 would do what we are trying to accomplish:
if (empty($this->file_title) && !empty($this->file_name)) {
$this->file_title = $this->file_name;
}


Unfortunately, if I assign a value to $this->file_name, I get an unknown column error because there is no column in the table for the filename.

Adding
$this->file_title = pathinfo($this->file_url, PATHINFO_BASENAME);
at line 143 solves this issue by replacing the file_title and still checking that the title is unique, however I am not sure if this could have a detrimental impact on other processes using the same code.

The better solution would be if the file_title value in the "Image Information" section of the form were not taken by the new upload and the submitted file_title was the actual filename of the uploaded file. That should occur earlier in the process, possibly by javascript right on the form or by replacing the value in the PHP right after the file upload occurs.



neo314

One additional note. I would suggest that in the renaming of the alias, the PATHINFO_FILENAME and PATHINFO_EXTENSION constants could be used with pathinfo to get the alias replacement to come out myimage_1.jpg instead of myimage.jpg_1. PATHINFO_FILENAME was added in PHP 5.2 so a regular expression or other routine might be better to extract the filename without the extension from the complete file name (PATHINFO_BASENAME).

This probably should only be done when the alias is the same as the filename, but for some weird reason, the alias is already in use since manually set aliases may not have an extension of look like a filename.

bytelord

Hey neo,

The file_name value is empty when editing for that reason you get an exception. When uploading a new image then the file_type is not empty.

Is there that i was trying to explain the for sequence number creation you will need to create a function that will search the database for same file_name, retrieve an array from the db, compare, make a sequence number, validate it to be sure, placed on file_title.

At your code snippet $this->file_title = pathinfo($this->file_url, PATHINFO_BASENAME); i don't think will work, you will need something line
<?php


$this->file_title= basename($this->file_url); //will return filename.jpg for example
or
$this->file_title= basename($this->file_url,'.jpg'); // will return filename

or you can use explode or combination with substr

btw, never tested the above ... just write it here...

BUT, in any case each time you save your media file the file_title will be equal to file_name and you will not be able to edit the "value", so if is equal there is no reason to use it or to exist at all :) :)

Regards
Production: Joomla 2.5.8 | VM 2.0.14 | PHP 5.3.13
Testing     : Joomla 2.5.8 | VM 2.0.16 | PHP 5.3.8
Testing     : Joomla 2.5.8 |    VM 2.1   | PHP 5.3.8

- Don't Forget to mark thread as solved when it is solved!
- Please do not PM with support questions, use the forum!

neo314

Another, possible better approach to hacking the problem would be to instead add at line 159 this:
if (!empty($unique_id)) {
$this->file_title = pathinfo($this->file_url, PATHINFO_BASENAME);
$q = 'SELECT * FROM `' . $this->_tbl . '` ';
$q .= 'WHERE `file_title`="' . $this->_db->getEscaped ($this->file_title) . '" AND `file_type`="' . $this->_db->getEscaped ($this->file_type) . '"';
$this->_db->setQuery ($q);
$unique_id = $this->_db->loadAssocList ();
}

That would only replace file_titles that are not unique with the filename and restest the new file_title (the filename) for uniqueness.