str_contains() gives HTTP ERROR 500 | Wordpress - php

I am trying to get list of all those files whose extension is jpeg,jpg or png and title contains '100x100' text.
I can easily get the list of files filtering by their extension, that's working fine but when I add a condition into it && str_contains($value,'100x100') then page is not working and gives HTTP ERROR 500
function:
function scan_files(){
$upload_dir = wp_upload_dir();
$folder = $upload_dir['basedir'];
$files = list_files( $folder );
foreach($files as $value){
if(pathinfo($value, PATHINFO_EXTENSION)=='jpeg'||pathinfo($value, PATHINFO_EXTENSION)=='jpg'||pathinfo($value, PATHINFO_EXTENSION)=='png' && str_contains($value,'100x100')){
$filtered_files[] = $value;
}
}
echo "<pre>";
print_r($filtered_files);
}
Can anyone help?
UPDATE
According #luk2302 's comment I have corrected the ) issue and page is working fine but values are not getting filtered, also according to #CBroe 's comment, I am using php7 so I replaced str_contains with strpos but still it's not giving expected results.
New Code:
function scan_files(){
$upload_dir = wp_upload_dir();
$folder = $upload_dir['basedir'];
$files = list_files( $folder );
foreach($files as $value){
if(pathinfo($value, PATHINFO_EXTENSION)=='jpeg'||pathinfo($value, PATHINFO_EXTENSION)=='jpg'||pathinfo($value, PATHINFO_EXTENSION)=='png' && strpos($value,'100x100')!==false){
$filtered_files[] = $value;
}
}
echo "<pre>";
print_r($filtered_files);
}

Change this line:
if(pathinfo($value, PATHINFO_EXTENSION)=='jpeg'||pathinfo($value, PATHINFO_EXTENSION)=='jpg'||pathinfo($value, PATHINFO_EXTENSION)=='png' && strpos($value,'100x100')!==false){
To:
if((pathinfo($value, PATHINFO_EXTENSION)=='jpeg'||pathinfo($value, PATHINFO_EXTENSION)=='jpg'||pathinfo($value, PATHINFO_EXTENSION)=='png') && strpos($value,'100x100')!==false){
Notice the extra parentheses around your pathinfo statements. You want to check if any of the extensions are true AND the path contains your key value. Your original code would only filter on filename if the extension was png.

Related

PHP doesn't send the reposnse

I have a very weird problem with php and I can't find any explanation for it.
I want to add this line of code to grab extension from the sent file:
$extension = array_pop( explode( "." , $_FILES["myFiles"]["name"][$key]);
but if i do so php doens't send a respond although the file is saved successfully. If I simply delete this line and hardcode ".jpg" instead $extension it sends the response as expected.
<?php
$response = array();
if (isset($_FILES)) {
foreach ($_FILES["myFiles"]["tmp_name"] as $key => $value) {
$user = $_POST["user"];
// when i add the line below it deosn't send the response!
$extension = array_pop( explode( "." , $_FILES["myFiles"]["name"][$key]) );
move_uploaded_file($value, "uploads/$user.$extension");
};
$response["msg"] = "image has been uploaded";
} else {
$response["msg"] = "selcect an image";
}
echo json_encode($response);
array_pop takes argument by reference. You can't provide argument directly from another function to array_pop.
Instead in your case you should do this:
$parts = explode("." , $_FILES["myFiles"]["name"][$key]);
$extension = array_pop($parts);
But! You should NEVER trust client's data, even if it's just a file extension. It is better to check extension itself (is it jpg, png, svg, gif), also check if the file is really an image, check size of that image, etc...

I have file in folder but how to get to know file extension

In my images folder have file
1_cover.???
2_cover.???
3_cover.???
4_cover.???
5_cover.???
I wanna get file extension 4_cover.???
How to write PHP code
==========
UPDATE
Thanks for all help me,
I can use this code
$images = glob("./images/4_cover.*");
print_r($images);
Is that what you are looking for ?
$info = new SplFileInfo('photo.jpg');
$path = $info->getExtension();
var_dump($path);
PHP Documentation
If you want to look in a directory for files, this might not be the best suited way to do your method but since you don't know what the file-type is, you can do something like this: (all code should be in order from top-bottom)
The directory housing all of your files
$directory = "public/images/headers/*";
The files gathered from the glob function, use print_r($files) to see all of the files gathered for debugging if there's an error going on
$files = glob( $directory );
The file you said you were looking for, if this is from a database you'll replace this data with data from the database
$filename_to_lookfor = '4_cover.';
If statements to check the file types and see if they're existant
$file_types_to_check_for = ['gif', 'jpg', 'png'];
foreach ($file_types_to_check_for as $filetype)
if (in_array( $filename_to_lookfor.$filetype, $files)
echo "This is a {$filetype} file!";
After reading more into glob - I'm not too experienced with it.
You can simply write this line:
if (count($files = glob( 'public/images/4_cover.*' )) != 0) $file = $files[0]; else echo 'No file with extension!';
or
$file = (count($files = glob('public/images/4_cover.*') != 0)) ? $files[0] : 'NO_FILE' ;
I apologize for the quite bad quality code, but that's what OP wants and that's the easiest way I could think to do that for him.
You can use the pathinfo function
$file = "file.php";
$path_parts = pathinfo($file);
$path_parts['extension']; // return => 'php'

Read Meta Tags from Files in a Directory

I'm trying to create a script that will read all of the other files in the directory and list them by grabbing the title meta tag for each one using the code below, but it's not working. If I'm reading the documentation correctly, get_meta_tags expects a URL by default, and if you want to point to a local file, you need to set the use_include_path parameter. But I don't think I'm doing that correctly.
$dir = '.';
$files = scandir($dir);
set_include_path($dir);
foreach ($files as &$value) {
$tags = get_meta_tags($value, true);
echo $tags['title'] . "<br/>";
}
According to the documentation it takes a URL or a filename-string. The only thing the second parameter is good for is if the files you want to parse are not on the current path, but are on the include path instead. That is not the case here, as you are already iterating over a path to get the filenames. You should do:
$dir = '.';
$files = scandir($dir);
foreach ($files as &$value) {
$tags = get_meta_tags($value);
echo $tags['title'] . "<br/>";
}

How to get the newest file in a directory in php

So I have this app that processes CSV files. I have a line of code to load the file.
$myFile = "data/FrontlineSMS_Message_Export_20120721.csv"; //The name of the CSV file
$fh = fopen($myFile, 'r'); //Open the file
I would like to find a way in which I could look in the data directory and get the newest file (they all have date tags so they would be in order inside of data) and set the name equal to $myFile.
I really couldn't find and understand the documentation of php directories so any helpful resources would be appreciated as well. Thank you.
Here's an attempt using scandir, assuming the only files in the directory have timestamped filenames:
$files = scandir('data', SCANDIR_SORT_DESCENDING);
$newest_file = $files[0];
We first list all files in the directory in descending order, then, whichever one is first in that list has the "greatest" filename — and therefore the greatest timestamp value — and is therefore the newest.
Note that scandir was added in PHP 5, but its documentation page shows how to implement that behavior in PHP 4.
For a search with wildcard you can use:
<?php
$path = "/var/www/html/*";
$latest_ctime = 0;
$latest_filename = '';
$files = glob($path);
foreach($files as $file)
{
if (is_file($file) && filectime($file) > $latest_ctime)
{
$latest_ctime = filectime($file);
$latest_filename = $file;
}
}
return $latest_filename;
?>
My solution, improved solution from Max Hofmann:
$ret = [];
$dir = Yii::getAlias("#app") . "/web/uploads/problem-letters/{$this->id}"; // set directory in question
if(is_dir($dir)) {
$ret = array_diff(scandir($dir), array(".", "..")); // get all files in dir as array and remove . and .. from it
}
usort($ret, function ($a, $b) use ($dir) {
if(filectime($dir . "/" . $a) < filectime($dir . "/" . $b)) {
return -1;
} else if(filectime($dir . "/" . $a) == filectime($dir . "/" . $b)) {
return 0;
} else {
return 1;
}
}); // sort array by file creation time, older first
echo $ret[count($ret)-1]; // filename of last created file
Here's an example where I felt more confident in using my own validator rather than simply relying on a timestamp with scandir().
In this context, I want to check if my server has a more recent file version than the client's version. So I compare version numbers from the file names.
$clientAppVersion = "1.0.5";
$latestVersionFileName = "";
$directory = "../../download/updates/darwin/"
$arrayOfFiles = scandir($directory);
foreach ($arrayOfFiles as $file) {
if (is_file($directory . $file)) {
// Your custom code here... For example:
$serverFileVersion = getVersionNumberFromFileName($file);
if (isVersionNumberGreater($serverFileVersion, $clientAppVersion)) {
$latestVersionFileName = $file;
}
}
}
// function declarations in my php file (used in the forEach loop)
function getVersionNumberFromFileName($fileName) {
// extract the version number with regEx replacement
return preg_replace("/Finance D - Tenue de livres-darwin-(x64|arm64)-|\.zip/", "", $fileName);
}
function removeAllNonDigits($semanticVersionString) {
// use regex replacement to keep only numeric values in the semantic version string
return preg_replace("/\D+/", "", $semanticVersionString);
}
function isVersionNumberGreater($serverFileVersion, $clientFileVersion): bool {
// receives two semantic versions (1.0.4) and compares their numeric value (104)
// true when server version is greater than client version (105 > 104)
return removeAllNonDigits($serverFileVersion) > removeAllNonDigits($clientFileVersion);
}
Using this manual comparison instead of a timestamp I can achieve a more surgical result. I hope this can give you some useful ideas if you have a similar requirement.
(PS: I took time to post because I was not satisfied with the answers I found relating to the specific requirement I had. Please be kind I'm also not very used to StackOverflow - Thanks!)

Exclude hidden files from scandir

I am using the following code to get a list of images in a directory:
$files = scandir($imagepath);
but $files also includes hidden files. How can I exclude them?
On Unix, you can use preg_grep to filter out filenames that start with a dot:
$files = preg_grep('/^([^.])/', scandir($imagepath));
I tend to use DirectoryIterator for things like this which provides a simple method for ignoring dot files:
$path = '/your/path';
foreach (new DirectoryIterator($path) as $fileInfo) {
if($fileInfo->isDot()) continue;
$file = $path.$fileInfo->getFilename();
}
$files = array_diff(scandir($imagepath), array('..', '.'));
or
$files = array_slice(scandir($imagepath), 2);
might be faster than
$files = preg_grep('/^([^.])/', scandir($imagepath));
function nothidden($path) {
$files = scandir($path);
foreach($files as $file) {
if ($file[0] != '.') $nothidden[] = $file;
return $nothidden;
}
}
Simply use this function
$files = nothidden($imagepath);
I encountered a comment from php.net, specifically for Windows systems: http://php.net/manual/en/function.filetype.php#87161
Quoting here for archive purposes:
I use the CLI version of PHP on Windows Vista. Here's how to determine if a file is marked "hidden" by NTFS:
function is_hidden_file($fn) {
$attr = trim(exec('FOR %A IN ("'.$fn.'") DO #ECHO %~aA'));
if($attr[3] === 'h')
return true;
return false;
}
Changing if($attr[3] === 'h') to if($attr[4] === 's') will check for system files.
This should work on any Windows OS that provides DOS shell commands.
I reckon because you are trying to 'filter' out the hidden files, it makes more sense and looks best to do this...
$items = array_filter(scandir($directory), function ($item) {
return 0 !== strpos($item, '.');
});
I'd also not call the variable $files as it implies that it only contains files, but you could in fact get directories as well...in some instances :)
use preg_grep to exclude files name with special characters for e.g.
$dir = "images/";
$files = preg_grep('/^([^.])/', scandir($dir));
http://php.net/manual/en/function.preg-grep.php
Assuming the hidden files start with a . you can do something like this when outputting:
foreach($files as $file) {
if(strpos($file, '.') !== (int) 0) {
echo $file;
}
}
Now you check for every item if there is no . as the first character, and if not it echos you like you would do.
Use the following code if you like to reset the array index too and set the order:
$path = "the/path";
$files = array_values(
preg_grep(
'/^([^.])/',
scandir($path, SCANDIR_SORT_ASCENDING)
));
One line:
$path = "daten/kundenimporte/";
$files = array_values(preg_grep('/^([^.])/', scandir($path, SCANDIR_SORT_ASCENDING)));
scandir() is a built-in function, which by default select hidden file as well,
if your directory has only . & .. hidden files then try selecting files
$files = array_diff(scandir("path/of/dir"),array(".","..")) //can add other hidden file if don't want to consider
I am still leaving the checkmark for seengee's solution and I would have posted a comment below for a slight correction to his solution.
His solution masks the directories(. and ..) but does not mask hidden files like .htaccess
A minor tweak solves the problem:
foreach(new DirectoryIterator($curDir) as $fileInfo) {
//Check for something like .htaccess in addition to . and ..
$fileName = $fileInfo->getFileName();
if(strlen(strstr($fileName, '.', true)) < 1) continue;
echo "<h3>" . $fileName . "</h3>";
}

Categories