PHP' glob() to select images - php

In my case I have a folder with a lot of images. In my source I want to get all images of ONE product.
E.g the product ID (PID) is 12345, in my folder I have images like:
123456789.jpg
123.jpg
1234.png
12345.png
12345-1.jpg
123456-1.bmp
12345-2.gif
The images I want to select is:
12345.png
12345-1.jpg
12345-2.gif
All other images or not from that product.
At the moment I select them like:
glob("path/to/the/images/" . $product_id . "*.*", GLOB_BRACE);
problem is.. this also brings me images like:
123456789.jpg
123456-1.bmp
Is it possible to say: bring me all images that matches the PID followed by a DOT (.) and all images that matches the PID followed by a MINUS (-) ?
I am testing it here and of course in my source since a while but can't find a solution.

I think this is what you need:
glob("path/to/the/images/" . $product_id . "[.-]*", GLOB_BRACE);

You could do this as an if statement, like the below
if(glob("path/to/the/images/*" . $product_id . ".*", GLOB_BRACE)
OR glob("path/to/the/images/" . $product_id . "-*", GLOB_BRACE)) {
//DO Stuff
}

Related

Remove Prestashop orphan images not stored in DB

I need to clean a shop running Prestashop, actually 1.7, since many years.
With this script I removed all the images in the DB not connected to any product.
But there are many files not listed in the DB. For example, actually I have 5 image sizes in settings, so new products shows 6 files in the folder (the 5 above and the imageID.jpg file) but some old product had up to 18 files. Many of these old products have been deleted but in the folder I still find all the other formats, like "2026-small-cart.jpg".
So I tried creating a script to loop in folders, check image files in it and verify if that id_image is stored in the DB.
If not, I can delete the file.
It works but obviously the loop is huge and it stops working as long as I change the starting path folder.
I've tried to reduce the DB queries storing some data (to delete all the images with the same id with a single DB query), but it still crashes as I change the starting path.
It only works with two nested loops (really few...).
Here is the code. Any idea for a better way to get the result?
Thanks!
$shop_root = $_SERVER['DOCUMENT_ROOT'].'/';
include('./config/config.inc.php');
include('./init.php');
$image_folder = 'img/p/';
$image_folder = 'img/p/2/0/3/2/'; // TEST, existing product
$image_folder = 'img/p/2/0/2/6/'; // TEST, product deleted from DB but files in folder
//$image_folder = 'img/p/2/0/2/'; // test, not working...
$scan_dir = $shop_root.$image_folder;
// will check only images...
global $imgExt;
$imgExt = array("jpg","png","gif","jpeg");
// to avoid multiple queries for the same image id...
global $lastID;
global $delMode;
echo "<h1>Examined folder: $image_folder</h1>\r\n";
function checkFile($scan_dir,$name) {
global $lastID;
global $delMode;
$path = $scan_dir.$name;
$ext = substr($name,strripos($name,".")+1);
// if is an image and file name starts with a number
if (in_array($ext,$imgExt) && (int)$name>0){
// avoid extra queries...
if ($lastID == (int)$name) {
$inDb = $lastID;
} else {
$inDb = (int)Db::getInstance()->getValue('SELECT id_product FROM '._DB_PREFIX_.'image WHERE id_image ='.((int) $name));
$lastID = (int)$name;
$delMode = $inDb;
}
// if haven't found an id_product in the DB for that id_image
if ($delMode<1){
echo "- $path has no related product in the DB I'll DELETE IT<br>\r\n";
//unlink($path);
}
}
}
function checkDir($scan_dir,$name2) {
echo "<h3>Elements found in the folder <i>$scan_dir$name2</i>:</h3>\r\n";
$files = array_values(array_diff(scandir($scan_dir.$name2.'/'), array('..', '.')));
foreach ($files as $key => $name) {
$path = $scan_dir.$name;
if (is_dir($path)) {
// new loop in the subfolder
checkDir($scan_dir,$name);
} else {
// is a file, I'll check if must be deleted
checkFile($scan_dir,$name);
}
}
}
checkDir($scan_dir,'');
I would create two files with lists of images.
The first file is the result of a query from your database of every image file referenced in your data.
mysql -BN -e "select distinct id_image from ${DB}.${DB_PREFIX}image" > all_image_ids
(set the shell variables for DB and DB_PREFIX first)
The second file is every image file currently in your directories. Include only files that start with a digit and have an image extension.
find img/p -name '[0-9]*.{jpg,png,gif,jpeg}' > all_image_files
For each filename, check if it's in the list of image ids. If not, then output the command to delete the file.
cat all_image_files | while read filename ; do
# strip the directory name and convert filename to an integer value
b=$(basename $filename)
image_id=$((${b/.*/}))
grep -q "^${image_id}$" all_image_ids || echo "rm ${filename}"
done > files_to_delete
Read the file files_to_delete to visually check that the list looks right. Then run that file as a shell script:
sh files_to_delete
Note I have not tested this solution, but it should give you something to experiment with.

Search text files and display results with PHP

I have a folder (blogfiles/posts) with various text files, numbered (1.txt, 2.txt, 3.txt...) and they each hold a post for a blog (I haven't learned SQL yet). I'm trying to make a search engine for it that will take a query from a text box (done with this part), then search the files for each word in the query, and return the results (possibly in order of the number of times the word occurs).
Each text file looks like this:
Title on Line 1
Date Posted on Line 2 (in Month Date, Year form)
Post body to search on lines 3 and up
I currently have this code:
<?php
$q = $_GET["q"];
$qArray = explode(" ", $q);
//preparing files
$post_directory = "blogfiles/posts/";
$files = scandir($post_directory, 1);
$post_count = (count($files)) - 2;
$files = array_pop($files); // there are 2 server files I want to ignore (#1)
$files = array_pop($files); // there are 2 server files I want to ignore (#2)
foreach ($files as $file) {
//getting title
$post_path = $post_directory . $file;
$post_filecontents = file($post_path);
$post_title = $post_filecontents[0];
echo "<tr><td>" . $post_title . "</td></tr>";
}
if ($post_count > 2) {
$postPlural = "s";
}
echo "<tr><td>" . $post_count . " post" . $postPlural . ".";
?>
I'll apologize now for the formatting, I was trying to separate it to troubleshoot.
Any help to get this working would be greatly appreciated.
There are many ways to search files.
use preg_match_all function to match pattern for each file.
use system() function to run external command like grep (only available under *nix).
use strpos function ( not recommended because of low performance and lack of support of pattern ).
If you will face a big traffic you'd better use pre-build indexes to accelerate the search. for example split the posts into tokens ( words ) and add position info along with the words, when user search the some words you can just split the words first and then look for the indexes. It's simpler to discribe this method than to implement it. You may need a existing full-text search engine like Apache Lucene.

How would I link to thumbnails in a subdirectory, when using php to get a list of images?

I'm sorry if the title is a little vague ... I'm still relatively new at PHP (3 months or so) Also, my native tongue is not English, so please bear with me :) I have also searched this site and google extensively to try and find a solution, but without any luck.
I have a script set up in my images directory that scans all the subdirectories, and then outputs a list of links that, if clicked, will take you to a page, where all the images of the selected subdirectory are displayed. The path to such a page would be:
www.mysite.com/images/list_images.php?folderName=RandomFolder
The code for this:
images/index.php
<?php
$path = 'images/' ;
$results = scandir($path);
for ($i=0;$i<count($results);$i++)
{
$result=$results[$i];
if ($result === '.' or $result === '..')
continue;
if (is_dir($path . '/' . $result))
{
echo "<a href='list_images.php?folderName=$result'>$result</a><br/>";
}
}
?>
--------------------
list_images.php
<?php
if(isset($_GET['folderName']))
$folder=$_GET['folderName'];
$path = 'images/'.$folder.'/' ;
$images = glob($path . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
foreach ($images as $image)
{
echo "<a href='$image'><img src='$image'/></a>";
}
?>
Now, my question:
In each of my image subdirectories I have another subdirectory called 'thumbs', that contains - yes, you guessed it - thumbnails. Each thumbnail is named exactly the same as its corresponding file in the directory above it. Now, how would I make the img src in the above code to point to the thumb?
Any help would be very welcome! Thank you in advance!
EDIT:
I looked over my code again, and I made few extra lines. It still doesn't work, but at least it now outputs thumbnails, which links to the larger image. Here's the new code:
list_images.php
if (isset($_GET['folderName'])) $folder=$_GET['folderName'];
$path = 'images/'.$folder.'/' ;
$thumb_path = ''.$path.'/thumbs/';
$thumbs = glob($thumb_path . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
$images = glob($path . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
foreach ($thumbs as $thumb){
foreach ($images as $image){
echo "<a class='fancybox' href='$image'><img src='$thumb'/></a>";
}
}
It kinda works now. The only problem is, that it outputs 13 identical thumbnails to each picture - and it does it 13 times (for a directory containing 13 image files) so there is 169 thumbnails in total.
Any ideas how to fix this?
If you are sure that the folder name is thumbs, there is no reason you can't hardcode this. Take a look at the following.
echo "<a href='$image'><img src='thumbs/$image'/></a>";
You could do a str_replace on the path.
If the path to the image is mydir\image01\pic01.jpg
str_replace('image01','image01\thumb',$image);
would point to mydir\image01\thumb\pic01.jpg

Deleting Files In A Directory Based On A Table

First of all, i would like to explain my condition right now.
I'm using PHP as my programming language.
I have a table named "Produk". It keeps every product name. Example value "TWC0001" in its id_produk column.
Every product have its own images, and stored in ./images/Produk/ directory.
the problem is, this project has been working about 1 years ago, and when the users delete a product, the product's images didn't deleted too. So, it still staying in ./images/Produk/ directory. It means, that file become a garbage right?
Case Example :
in the "Produk" table, column "id_produk" i have 3 rows :
"TWC0001","TWC0002","TWC0003".
Of course each of those rows have its own images that stored in ./images/Produk/
Each of those files named :
"TWC0001.jpg", "TWC0002.jpg", "TWC0003.jpg"
Case : A user logged in and deleted row "TWC0002", of course the "TWC0002.jpg" file still exist.
Problem : I want to delete all ".jpg" files that didn't listed in the "Produk" table anymore.
I've been doing this :
//listing all the ".jpg" files
$arrayfiles=scandir("../images/Produk/");
//getting all the product list
$sql="select * from produk";
$produk=mysql_query($sql,$conn) or die("Error : ".mysql_error());
foreach($arrayfiles as $key=>$value)
{
while($row=mysql_fetch_array($produk,MYSQL_ASSOC))
{
///here is the part i've been confused of.
}
}
PHP function to delete file is "unlink()";
Please anybody help me out of this.
The following code will produce an array with all the images that have no corresponding product record. I've left off the unlink command so you can do some reviewing process first.
$sql = "SELECT * FROM Produk";
$result = mysql_query($sql);
$existing_products = array();
while ($row = mysql_fetch_array($result))
$existing_products[] = $row["id_produk"] . ".jpg";
$existing_images = array();
foreach(glob("../images/Produk/*.jpg") as $v)
$existing_images[] = str_replace("../images/Produk/", "", $v);
$images_to_delete = array_diff($existing_images, $existing_products);
try this
$it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator('../images/Produk/'));
$regx = new RegexIterator( $it, '/^.*\.jpg$/i', // only matched text will be returned
RecursiveRegexIterator::GET_MATCH );
foreach ($regx as $file) {
echo $file[0] , "\n";
unlink($file[0]);
}
this will find all JPG files in the given folders and subfolders and will delete it
I would recommend following:
make directory listing of "Images" direcotry by
dir /b > filelist.txt (windows)
or
ls -1 > filelist.txt (linux)
You will have now list of existing files which should be imported to some temp table in mysql.
Now write simple SQL to select files without apropriate products (don't forget to append .JPG suffix).
with list of files to be deleted you can simply create file_get_contents and foreach loop unlink.
Reason why I recommend this is security.You can review what will be deleted.
Once you run script, there is no undo (just from backup).
foreach(glob('../images/Produk/*.jpg') as $file) {
if(is_file($file))
#unlink($file);
}

Displaying an image in php using two different variables?

I have my root folder, and within my root folder is a folder named images.
Within the images folder is 4 subfolders, each named after a Suit of cards.
Within each Suit folder, I have 13 pictures named after cards. Ace.jpg, Two.jpg, etc.
Within my Code, I declare each suit and card as a variable.
/*Array used to select a random number*/
$CardNumber = array();
$CardNumber[0]="Ace";
$CardNumber[1]="Two";
$CardNumber[2]="Three";
$CardNumber[3]="Four";
$CardNumber[4]="Five";
$CardNumber[5]="Six";
$CardNumber[6]="Seven";
$CardNumber[7]="Eight";
$CardNumber[8]="Nine";
$CardNumber[9]="Ten";
$CardNumber[10]="Jack";
$CardNumber[11]="Queen";
$CardNumber[12]="King";
/*Array used to select a random suit.*/
$CardSuit = array();
$CardSuit[0]="Clubs";
$CardSuit[1]="Diamonds";
$CardSuit[2]="Hearts";
$CardSuit[3]="Spades";
After a player picks a Card and a Suit, is there anyway to display the card he chose?
E.G. If You picked the 5 of Clubs, it would display the picture named Five.jpg from the Clubs folder?
As far as I understand you just need to create an image tag with the src pointing to the right file in the right directory...
$suit = 'Hearts';
$card = 'Queen';
printf('<img src="%s/%s.jpg">', $suit, $card);
I guess you could do the following if you want to pick a random card
$CNkey = array_rand($CardNumber);
$CSKey = array_rand($CardSuit);
$randomCardNumber = $CardNumber[$CNKey];
$randomCardSuit = $CardSuit[$CSKey];
$image = '/images/' . $randomCardSuit . '/' . $randomCardNumber . '.jpg'; // or any other image extensions
echo '<img src="' . $image . '">';

Categories