Hi,

I have a extension in my opencart store that uses a .csv file to import data into products. The .csv file is a stock inventory list from a tyre manufacturer. The extension uses a string value of the image filepath that get inserted into the database.

The issue I have is that the image name in the inventory doesn't include the file's extension. There are around 5000 products and I have all the images ready uploaded in a directory on my server.

I could go through and add them into the csv file manually but the stock inventory will be sent across weekly and this would become time consuming and costly for the client (and tedious for me).

As there are only 2 file extensions used (.GIF and .jpg) I have created an if statement that will search for the file in that directory with that extension then return it with that extension attached if it exists, using the is_file() function. A similair version of this has worked for me, although the below snippet of code has had variables like the $file changed to match the function I need to work with.

                    $file = $this->params['images_dir'].$image;


                    if (is_file(DIR_IMAGE . $file.'.GIF')) {

                        $file = $file.'.GIF';
                        echo "The file $file exists in gif format <br />";
                    } elseif (is_file(DIR_IMAGE . $file.'.jpg')) {

                        $file = $file.'.jpg';
                        echo "The file $file exists in jpg format<br />";
                    } else {
                        $this->lastError = "File not found " . DIR_IMAGE . $file ." extension <br />";
                        return false;
                    }

Speaking to the developer of the extension they said that the check has to be added to the getImageFile() function within one file of the code. This is where I get stuck.

Here is the original function in question:

protected function getImageFile($image) {
        $this->lastError = '';

        if (empty($image))
            return false;

        $image = trim($image);

        $file = '';
        if ($this->isUrl($image)) {

            // download file and parse the path
            //
            $image = htmlspecialchars_decode($image);
            $tmp = str_replace(array(' '), array('%20'), $image);

            $content = $this->getFileContentsByUrl($tmp);
            if (empty($content)) {
                $this->lastError = "File content is empty for $tmp";
                return false;
            }

            $url_info = @parse_url($image);

            if (empty($url_info)) {
                $this->lastError = "Invalid URL data $url";
                return false;
            }

            //get relative image directory to $images_dir

            $fullname  = '';
            $images_dir = str_replace("\\", '/', $this->params['incoming_images_dir']);

            if (!empty($url_info['path'])) {
                $url_info['path'] = urldecode($url_info['path']);

                $path_info = pathinfo($url_info['path']);
                $path_info['dirname'] = $this->strip($path_info['dirname'], array("\\","/"));
                if (!empty($path_info['dirname'])) {
                    $images_dir = $images_dir . $path_info['dirname'] . '/';
                    if (!file_exists(DIR_IMAGE . $images_dir)) {
                        if (!mkdir(DIR_IMAGE . $images_dir, 0755, true)) {
                            $this->lastError = "Script cannot create directory: $images_dir";
                            return false;
                        }
                    }
                }
            }

            // get file name to $filename

            $tmp_file = tempnam(DIR_IMAGE . $images_dir, "tmp");

            $size = file_put_contents($tmp_file, $content);
            if (empty($size)) {
                $this->lastError = "Cannot save new image file: $tmp_file";
                return false;
            }

            $image_info = getimagesize($tmp_file);
            if (empty($image_info)) {
                $this->lastError = "getimagesize returned empty info for the file: $image";
                return false;
            }

            if (!empty($url_info['query'])) {
                $filename = '';
                if (!empty($path_info['basename'])) {
                    $filename = $path_info['basename'];
                }
                $query = $this->normalizeFilename($url_info['query']);
                $filename = $filename . $query . image_type_to_extension($image_info[2]);

            } else {
                $filename = $path_info['basename'];
                if (empty($path_info['extension'])) {
                    $filename = $filename . image_type_to_extension($image_info[2]);
                }
            }

            if (is_file(DIR_IMAGE.$images_dir.$filename)) {
                @unlink(DIR_IMAGE.$images_dir.$filename);
            }

            if (!is_file(DIR_IMAGE.$images_dir.$filename)) {
                if (!rename($tmp_file, DIR_IMAGE.$images_dir.$filename)) {
                    $this->lastError = "rename operation failed. from $tmp_file to " . DIR_IMAGE.$images_dir.$filename;
                    return false;
                }

                if (!chmod(DIR_IMAGE . $images_dir . $filename, 0644)) {
                    $this->lastError = "chmod failed for file: $filename";
                    return false;
                }
            }

            $file = $images_dir . $filename;


        } else {

            //
            // if the image is a regular file
            //

            $file = $this->params['images_dir'].$image;
            if (!is_file(DIR_IMAGE . $file)) {
                $this->lastError = "File not found " . DIR_IMAGE . $file;
                return false;
            }
        }

        return $file;
    }

Now looking through it I believe my check has to be added in the last else statement (to check if the image is a regular file) but im struggling with this.

Here is what I have come up with so far (for the else statement) but it doesnt work. The extensions isnt added onto the $file variable and so causes a file not found error when running the uploader.

} else {

            //
            // if the image is a regular file
            //

            $file = $this->params['images_dir'].$image;

            /* reece chnages start */

                    if (is_file(DIR_IMAGE . $file.'.GIF')) {

                        $file = $file.'.GIF';
                        echo "The file $file exists in gif format <br />";
                    } elseif (is_file(DIR_IMAGE . $file.'.jpg')) {

                        $file = $file.'.jpg';
                        echo "The file $file exists in jpg format<br />";
                    } else {
                        $this->lastError = "File not found " . DIR_IMAGE . $file ." extension <br />";
                        return false;
                    }

                    /* reece chnages end */


            //if (!is_file(DIR_IMAGE . $file)) {
            //  $this->lastError = "File not found " . DIR_IMAGE . $file;
            //  return false;
            //}
        }

        return $file;

For all I know I may be placing the check in the wrong place, I am really not sure.

Could anyone please point me in the right direction? I know a little bit about PHP but am no means an expert so please bare with me if I ask questions that might seem simple.

I can send you the whole php file if you want to look at it.

All help is greatly appreciated, thank you.

Recommended Answers

All 8 Replies

Looking at the code you could get your result just by replacing:

return $file;

With:

return $file . image_type_to_extension($image_info[2]);

But you should already get this, since it is used between line 61 and 80.

Hi,

I hope this makes sense, it does in my head.

Thanks for your reply. I probably should have said that this .csv file will check to see if that value is a URL (in which case it will download the image) or just a filename/filepath in which case it will check against the iamges on the server.

Im pretty sure that lines 10 to 100 are for grabbing the image from a URL (looking at the isUrl() inside the if statement) and the following else statement is if its a regular filepath.

Also im not sure the image_type_to_extension() would work as the value in the csv doesnt include the file extension.

Perhaps I need to put my check before the if statement and see is that works?

image_type_to_extension() will work because it is not based on the file extension, it read the mime type of the file, you can achieve the same result by using finfo: http://www.php.net/manual/en/function.finfo-file.php

And now it makes perfect sense, I wasn't sure about some of those methods, your explanation clarifies my doubts. Try this:

# last part of getImagefile() ...

    } else {

        $file = $this->params['images_dir'].$image;

        //
        // if the image is a regular file
        //

        if(is_file($file.'.jpg') || is_file($file.'.GIF'))
        {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            switch(finfo_file($finfo, $file))
            {
                case 'image/jpeg':
                    $file = $file . '.jpg';
                    break;
                case 'image/gif':
                    $file = $file . '.GIF';
                    break;
            }
        }
    }

    return $file;
}

It's just an example but it should work fine. Just pay attention to uppercase, if you're using a linux box image.GIF will be considered different from image.gif. In practice my suggestion is the same solution of yours, the only difference is that I'm not applying $this->params['images_dir'] and DIR_IMAGE togheter. Have you checked the logs of the server to see if there are undefined paths?

Thank you for the reply.

I am using a linux box which is why its .GIF.

I have tried this and I'm receiving no error messages at all. In the importer logs or the server logs. Which to me would say its working, but checking the database its just importing the filenames without the extension.

I tried the following as well, thinking it wasn't finding the file so ignoring the if statement:

} else {

            //
            // if the image is a regular file
            //

            $file = $this->params['images_dir'].$image;


            if(is_file(DIR_IMAGE . $file.'.jpg') || is_file(DIR_IMAGE . $file.'.GIF'))
                {
                    $finfo = finfo_open(FILEINFO_MIME_TYPE);
                    switch(finfo_file($finfo, $file))
                    {
                        case 'image/jpeg':
                            $file = $file . '.jpg';
                            break;
                        case 'image/gif':
                            $file = $file . '.GIF';
                            break;
                    }
                }
        }

        return $file;
    }

The error that was returned is:

[9:43:16] Server error (status=200). Details:
Warning: fopen(/home/easytyr1/public_html/system/logs/) [function.fopen]: failed to open stream: Is a directory in /home/easytyr1/public_html/system/library/log.php on line 12

Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/easytyr1/public_html/system/library/log.php on line 14

Warning: fclose() expects parameter 1 to be resource, boolean given in /home/easytyr1/public_html/system/library/log.php on line 16

Over and over again. This error message makes little sense to me, I presume the value used in $finfo is wrong somewhere.

It's too my understanding that DIR_IMAGE is a global variable in OpenCart that defines the default image directory. Then the $this->params['images_dir'] defines the subfolder inside the images directory that I want to search for the images in.

DIR_IMAGE . $this->params['images_dir'] . $file . "the extension" should be where the image is located on the server. Yet I want to insert $file . "the extension" into the database.

but checking the database its just importing the filenames without the extension.

Are you sure the data is not inserted in the database table independently from this method? At this point it's hard to suggest the correct approach, can you show the part relative to the insert?

Also you can verify the values of DIR_IMAGE and $this->params['images_dir'] just by echoing them.

1) Warning: fopen(/home/easytyr1/public_html/system/logs/) [function.fopen]: failed to open stream: Is a directory in /home/easytyr1/public_html/system/library/log.php on line 12

From http://www.php.net/manual/en/function.fopen.php#105465 it seems you are using something liken,please change code according to this.

<?php
$fplog = fopen('ipn.log','a');
?>

After the migration, however, I received the following error message:

Warning: fopen(ipn.log) [function.fopen]: failed to open stream: Permission denied in D:\home\server_name\log_test.php on line 21

I had to change the code to the following to get it to work:

<?php
$logfile = $_SERVER['DOCUMENT_ROOT'].'\ipn.log';
$fplog = fopen($logfile,'a');
?>

2)Warning: fwrite() expects parameter 1 to be resource, boolean given in /home/easytyr1/public_html/system/library/log.php on line 14

http://stackoverflow.com/questions/11742682/php-5-3-fwrite-expects-parameter-1-to-be-resource-error

So by echoing out a few values I get the following values:

DIR_IMAGE = /home/easytyr1/public_html/image/ (this is the directory to the images)

$this->params['images_dir'] = data/tyre_images/ (this is the folder in that directory)

$file = data/tyre_images/MATADOR_MP16 (this is an example before the check to see if it exists and add the extension)

As your finfo_open kept returning the "failed to open stream" I reverted back to my check.

Here is where I am at at the moment, the code is below. The code checks against the right filepath and adds the extension. Some of the image filenames are added to the database with the correct extension. Ive recently found out that I don't have some of the images so some come back empty.

#end of the getImageFile() function

} else {

            //
            // if the image is a regular file
            //

            $file = $this->params['images_dir'].$image;


//          if(is_file(DIR_IMAGE . $file.'.jpg') || is_file(DIR_IMAGE . $file.'.GIF'))
//              {
//                  $finfo = finfo_open(FILEINFO_MIME_TYPE);
//                  switch(finfo_file($finfo, $file))
//                  {
//                      case 'image/jpeg':
//                          $file = $file . '.jpg';
//                          break;
//                      case 'image/gif':
//                          $file = $file . '.GIF';
//                          break;
//                  }
//              }

                if (is_file(DIR_IMAGE . $file.'.GIF')) {
                        $file = $file.'.GIF';
                } elseif (is_file(DIR_IMAGE . $file.'.jpg')) {
                        $file = $file.'.jpg';
                } else {
                        echo "This file $file doesn't exist in any format"; 
                }

            $echo_dirimage = DIR_IMAGE;
            echo "DIR_IMAGE = " . $echo_dirimage . "<br />";
            $echo_image__dir = $this->params['images_dir'];
            echo "images_dir = " . $echo_image__dir . "<br />";
            $echo_filepath = DIR_IMAGE . $file;
            echo "filepath = " . $echo_filepath . "<br />";
        }

        return $file;
    }

Im now getting an issue that after 12 seconds it stops running. This is the last line of the importer logs.

{"filesize":1688068,"offset":104758,"started_at":1377675716,"lines_processed":546,"products_created":0,"products_updated":545,"products_deleted":0,"categories_created":0,"errors":[],"status":"in_progress","col_count":31,"messages":null,"time_passed":"12 seconds ","completion_at":"6.21%"}

I can't find the part of the site where the code INSERT's the updated data into the database. I can send you the file via email if you want it.

Thank you for all your help so far, I feel we are getting somewhere.

Well these seems like the code I wrote at the beginning lol but it works. I have it uploading with no errors or the importer stopping.

I think the importer was stopping because I was echoing out too muhc, i cleaned up the code, ran it and it works.

Here is the final else statement.

} else {

            //
            // if the image is a regular file
            // and check the file extension - altered by reece
            //
            $file = $this->params['images_dir'].$image;



                    if (is_file(DIR_IMAGE . $file.'.GIF')) {
                        $file = $file.'.GIF';
                    } elseif (is_file(DIR_IMAGE . $file.'.jpg')) {
                        $file = $file.'.jpg';
                    } else {
                        $file = $file;  
                    }           
        }

        return $file;
    }

Thank you for your help cereal, I will mark this as solved.

commented: thanks for sharing! +11
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.