Regex extract variables from [shortcode] - php

After migrating some content from WordPress to Drupal, I've got som shortcodes that I need to convert:
String content:
Irrelevant tekst...
[sublimevideo class="sublime"
poster="http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png"
src1="http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v"
src2="(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v"
width="560" height="315"]
..more irrelevant text.
I need to find all variables within the shortcode [sublimevideo ...] and turn it into an array:
Array (
class => "sublime"
poster => "http://video.host.com/_previews/600x450/sbx-60025-00-da-FMT.png"
src1 => "http://video.host.com/_video/H.264/LO/sbx-60025-00-da-FMT.m4v"
src2 => "(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-FMT.m4v"
width => "560"
height => "315"
)
And preferably handle multiple instances of the shortcode.
I guess it can be done with preg_match_all() but I've had no luck.

This will give you what you want.
$data = 'Irrelevant tekst... [sublimevideo class="sublime" poster="http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png" src1="http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v" src2="(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v" width="560" height="315"] ..more irrelevant text.';
$dat = array();
preg_match("/\[sublimevideo (.+?)\]/", $data, $dat);
$dat = array_pop($dat);
$dat= explode(" ", $dat);
$params = array();
foreach ($dat as $d){
list($opt, $val) = explode("=", $d);
$params[$opt] = trim($val, '"');
}
print_r($params);
In anticipation of the next challenge you will face with processing short codes you can use preg_replace_callback to replace the short tag data with it's resultant markup.
$data = 'Irrelevant tekst... [sublimevideo class="sublime" poster="http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png" src1="http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v" src2="(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v" width="560" height="315"] ..more irrelevant text.';
function processShortCode($matches){
// parse out the arguments
$dat= explode(" ", $matches[2]);
$params = array();
foreach ($dat as $d){
list($opt, $val) = explode("=", $d);
$params[$opt] = trim($val, '"');
}
switch($matches[1]){
case "sublimevideo":
// here is where you would want to return the resultant markup from the shorttag call.
return print_r($params, true);
}
}
$data = preg_replace_callback("/\[(\w+) (.+?)]/", "processShortCode", $data);
echo $data;

You could use the following RegEx to match the variables:
$regex = '/(\w+)\s*=\s*"(.*?)"/';
I would suggest to first match the sublimevideo shortcode and get that into a string with the following RegEx:
$pattern = '/\[sublimevideo(.*?)\]/';
To get the correct array keys I used this code:
// $string is string content you specified
preg_match_all($regex, $string, $matches);
$sublimevideo = array();
for ($i = 0; $i < count($matches[1]); $i++)
$sublimevideo[$matches[1][$i]] = $matches[2][$i];
This returns the following array: (the one that you've requested)
Array
(
[class] => sublime
[poster] => http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png
[src1] => http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v
[src2] => (hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v
[width] => 560
[height] => 315
)

This is my interpretation, I come from a WordPress background and tried to recreate the setup for a custom php project.
It'll handle things like [PHONE] [PHONE abc="123"] etc
The only thing it falls flat on is the WordPress style [HERE] to [HERE]
Function to build a list of available shortcodes
// Setup the default global variable
function create_shortcode($tag, $function)
{
global $shortcodes;
$shortcodes[$tag] = $function;
}
define shortcodes individually, e.g. [IFRAME url="https://www.bbc.co.uk"]:
/**
* iframe, allows the user to add an iframe to a page with responsive div wrapper
*/
create_shortcode('IFRAME', function($atts) {
// ... some validation goes here
// The parameters that can be set in the shortcode
if (empty($atts['url'])) {
return false;
}
return '
<div class="embed-responsive embed-responsive-4by3">
<iframe class="embed-responsive-item" src="' . $atts['url'] . '">
</iframe>
</div>';
});
Then when you want to pass a block of html via the shortcode handling do... handle_shortcodes($some_html_with_shortcodes);
function handle_shortcodes($content)
{
global $shortcodes;
// Loop through all shortcodes
foreach($shortcodes as $key => $function){
$matches = [];
// Look for shortcodes, returns an array of ALL matches
preg_match_all("/\[$key([^_^\]].+?)?\]/", $content, $matches, PREG_UNMATCHED_AS_NULL);
if (!empty($matches))
{
$i = 0;
$full_shortcode = $matches[0];
$attributes = $matches[1];
if (!empty($attributes))
{
foreach($attributes as $attribute_string) {
// Decode the values (e.g. " to ")
$attribute_string = htmlspecialchars_decode($attribute_string);
// Find all the query args, looking for `arg="anything"`
preg_match_all('/\w+\=\"(.[^"]+)\"/', $attribute_string, $query_args);
$params = [];
foreach ($query_args[0] as $d) {
// Split the
list($att, $val) = explode('=', $d, 2);
$params[$att] = trim($val, '"');
}
$content = str_replace($full_shortcode[$i], $function($params), $content);
$i++;
}
}
}
}
return $content;
}
I've plucked these examples from working code so hopefully it's readable and doesn't have any extra functions exclusive to our setup.

As described in this answer, I'd suggest letting WordPress do the work for you using the get_shortcode_regex() function.
$pattern = get_shortcode_regex();
preg_match_all("/$pattern/",$wp_content,$matches);
This will give you an array that is easy to work with and shows the various shortcodes and affiliated attributes in your content. It isn't the most obvious array format, so print it and take a look so you know how to manipulate the data you need.

Related

Get between every strings

Below is a function that can get a string with two other strings without a problem,
function GetBetween($content,$start,$end){
$r = explode($start, $content);
if (isset($r[1])){
$r = explode($end, $r[1]);
return $r[0];
}
return '';
}
Let's say I have code like this:
<code>Sample one</code>
<code>Sample two</code>
<code>Sample three</code>
When using GetBetween($content,'<code>',</code>') Instead of returning something like array("Sample one","Sample two","Sample three") it will only return the first one which is "Sample one"
How can I get it to return EVERYTHING between the two things I specify? I would appreciate it if I could get a solution that isn't hardcoded with the "" tags because I will be needing this for many different things.
Firstly regex is not the correct tool for parsing HTML/XML instead you can simply use DOMDocument like as
$xml = "<code>Sample one</code><code>Sample two</code><code>Sample three</code>";
$dom = new DOMDocument;
$dom->loadHTMl($xml);
$root = $dom->documentElement;
$code_data = $root->getElementsByTagName('code');
$code_arr = array();
foreach ($code_data as $key => $value) {
$code_arr[] = $value->nodeValue;
}
print_r($code_arr);
Output:
Array
(
[0] => Sample one
[1] => Sample two
[2] => Sample three
)
I've had to use a function like this, so I keep it handy:
//where a = content, b = start, c = end
function getBetween($a, $b, $c) {
$y = explode($b, $a);
$len = sizeof($y);
$arr = [];
for ($i = 1; $i < $len; $i++)
$arr[] = explode($c, $y[$i])[0];
return $arr;
}
Anything beyond this, you'll need to start using DomDocument.
Guess you could try something like this,
function GetBetween($content,$tagname){
$pattern = "#<\s*?$tagname\b[^>]*>(.*?)</$tagname\b[^>]*>#s";
preg_match($pattern, $string, $matches);
unset($matches[0]);
return $matches;
}
$content= "<code>Sample one</code><code>Sample two</code><code>Sample three</code>";
//The matching items are:
print_r(GetBetween($content, 'code'));

PHP foreach overwrite value with array

I'm making a simple PHP Template system but I'm getting an error I cannot solve, the thing is the layout loads excellent but many times, can't figure how to solve, here my code
Class Template {
private $var = array();
public function assign($key, $value) {
$this->vars[$key] = $value;
}
public function render($template_name) {
$path = $template_name.'.tpl';
if (file_exists($path)) {
$content = file_get_contents($path);
foreach($this->vars as $display) {
$newcontent = str_replace(array_keys($this->vars, $display), $display, $content);
echo $newcontent;
}
} else {
exit('<h1>Load error</h1>');
}
}
}
And the output is
Title is : Welcome to my template system
Credits to [credits]
Title is : [title]
Credits to Credits to Alvaritos
As you can see this is wrong, but don't know how to solve it.
You're better off with strtr:
$content = file_get_contents($path);
$new = strtr($content, $this->vars);
print $new;
str_replace() does the replaces in the order the keys are defined. If you have variables like array('a' => 1, 'aa' => 2) and a string like aa, you will get 11 instead of 2. strtr() will order the keys by length before replacing (highest first), so that won't happen.
Use this:
foreach($this->vars as $key => $value)
$content = str_replace($key,$value,$content);
echo $content;

Parse Wordpress like Shortcode

I want to parse shortcode like Wordpress with attributes:
Input:
[include file="header.html"]
I need output as array, function name "include" and attributes with values as well , any help will be appreciated.
Thanks
Here's a utility class that we used on our project
It will match all shortcodes in a string (including html) and it will output an associative array including their name, attributes and content
final class Parser {
// Regex101 reference: https://regex101.com/r/pJ7lO1
const SHORTOCODE_REGEXP = "/(?P<shortcode>(?:(?:\\s?\\[))(?P<name>[\\w\\-]{3,})(?:\\s(?P<attrs>[\\w\\d,\\s=\\\"\\'\\-\\+\\#\\%\\!\\~\\`\\&\\.\\s\\:\\/\\?\\|]+))?(?:\\])(?:(?P<content>[\\w\\d\\,\\!\\#\\#\\$\\%\\^\\&\\*\\(\\\\)\\s\\=\\\"\\'\\-\\+\\&\\.\\s\\:\\/\\?\\|\\<\\>]+)(?:\\[\\/[\\w\\-\\_]+\\]))?)/u";
// Regex101 reference: https://regex101.com/r/sZ7wP0
const ATTRIBUTE_REGEXP = "/(?<name>\\S+)=[\"']?(?P<value>(?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?/u";
public static function parse_shortcodes($text) {
preg_match_all(self::SHORTOCODE_REGEXP, $text, $matches, PREG_SET_ORDER);
$shortcodes = array();
foreach ($matches as $i => $value) {
$shortcodes[$i]['shortcode'] = $value['shortcode'];
$shortcodes[$i]['name'] = $value['name'];
if (isset($value['attrs'])) {
$attrs = self::parse_attrs($value['attrs']);
$shortcodes[$i]['attrs'] = $attrs;
}
if (isset($value['content'])) {
$shortcodes[$i]['content'] = $value['content'];
}
}
return $shortcodes;
}
private static function parse_attrs($attrs) {
preg_match_all(self::ATTRIBUTE_REGEXP, $attrs, $matches, PREG_SET_ORDER);
$attributes = array();
foreach ($matches as $i => $value) {
$key = $value['name'];
$attributes[$i][$key] = $value['value'];
}
return $attributes;
}
}
print_r(Parser::parse_shortcodes('[include file="header.html"]'));
Output:
Array
(
[0] => Array
(
[shortcode] => [include file="header.html"]
[name] => include
[attrs] => Array
(
[0] => Array
(
[file] => header.html
)
)
)
)
Using this function
$code = '[include file="header.html"]';
$innerCode = GetBetween($code, '[', ']');
$innerCodeParts = explode(' ', $innerCode);
$command = $innerCodeParts[0];
$attributeAndValue = $innerCodeParts[1];
$attributeParts = explode('=', $attributeAndValue);
$attribute = $attributeParts[0];
$attributeValue = str_replace('"', '', $attributeParts[1]);
echo $command . ' ' . $attribute . '=' . $attributeValue;
//this will result in include file=header.html
$command will be "include"
$attribute will be "file"
$attributeValue will be "header.html"
I also needed this functionality in my PHP framework. This is what I've written, it works pretty well. It works with anonymous functions, which I really like (it's a bit like the callback functions in JavaScript).
<?php
//The content which should be parsed
$content = '<p>Hello, my name is John an my age is [calc-age day="4" month="10" year="1991"].</p>';
$content .= '<p>Hello, my name is Carol an my age is [calc-age day="26" month="11" year="1996"].</p>';
//The array with all the shortcode handlers. This is just a regular associative array with anonymous functions as values. A very cool new feature in PHP, just like callbacks in JavaScript or delegates in C#.
$shortcodes = array(
"calc-age" => function($data){
$content = "";
//Calculate the age
if(isset($data["day"], $data["month"], $data["year"])){
$age = date("Y") - $data["year"];
if(date("m") < $data["month"]){
$age--;
}
if(date("m") == $data["month"] && date("d") < $data["day"]){
$age--;
}
$content = $age;
}
return $content;
}
);
//http://stackoverflow.com/questions/18196159/regex-extract-variables-from-shortcode
function handleShortcodes($content, $shortcodes){
//Loop through all shortcodes
foreach($shortcodes as $key => $function){
$dat = array();
preg_match_all("/\[".$key." (.+?)\]/", $content, $dat);
if(count($dat) > 0 && $dat[0] != array() && isset($dat[1])){
$i = 0;
$actual_string = $dat[0];
foreach($dat[1] as $temp){
$temp = explode(" ", $temp);
$params = array();
foreach ($temp as $d){
list($opt, $val) = explode("=", $d);
$params[$opt] = trim($val, '"');
}
$content = str_replace($actual_string[$i], $function($params), $content);
$i++;
}
}
}
return $content;
}
echo handleShortcodes($content, $shortcodes);
?>
The result:
Hello, my name is John an my age is 22.
Hello, my name is Carol an my age is 17.
This is actually tougher than it might appear on the surface. Andrew's answer works, but begins to break down if square brackets appear in the source text [like this, for example]. WordPress works by pre-registering a list of valid shortcodes, and only acting on text inside brackets if it matches one of these predefined values. That way it doesn't mangle any regular text that might just happen to have a set of square brackets in it.
The actual source code of the WordPress shortcode engine is fairly robust, and it doesn't look like it would be all that tough to modify the file to run by itself -- then you could use that in your application to handle the tough work. (If you're interested, take a look at get_shortcode_regex() in that file to see just how hairy the proper solution to this problem can actually get.)
A very rough implementation of your question using the WP shortcodes.php would look something like:
// Define the shortcode
function inlude_shortcode_func($attrs) {
$data = shortcode_atts(array(
'file' => 'default'
), $attrs);
return "Including File: {$data['file']}";
}
add_shortcode('include', 'inlude_shortcode_func');
// And then run your page content through the filter
echo do_shortcode('This is a document with [include file="header.html"] included!');
Again, not tested at all, but it's not a very hard API to use.
I have modified above function with wordpress function
function extractThis($short_code_string) {
$shortocode_regexp = "/(?P<shortcode>(?:(?:\\s?\\[))(?P<name>[\\w\\-]{3,})(?:\\s(?P<attrs>[\\w\\d,\\s=\\\"\\'\\-\\+\\#\\%\\!\\~\\`\\&\\.\\s\\:\\/\\?\\|]+))?(?:\\])(?:(?P<content>[\\w\\d\\,\\!\\#\\#\\$\\%\\^\\&\\*\\(\\\\)\\s\\=\\\"\\'\\-\\+\\&\\.\\s\\:\\/\\?\\|\\<\\>]+)(?:\\[\\/[\\w\\-\\_]+\\]))?)/u";
preg_match_all($shortocode_regexp, $short_code_string, $matches, PREG_SET_ORDER);
$shortcodes = array();
foreach ($matches as $i => $value) {
$shortcodes[$i]['shortcode'] = $value['shortcode'];
$shortcodes[$i]['name'] = $value['name'];
if (isset($value['attrs'])) {
$attrs = shortcode_parse_atts($value['attrs']);
$shortcodes[$i]['attrs'] = $attrs;
}
if (isset($value['content'])) {
$shortcodes[$i]['content'] = $value['content'];
}
}
return $shortcodes;
}
I think this one help for all :)
Updating the #Duco's snippet, As it seems like, it's exploding by spaces which ruins when we have some like
[Image source="myimage.jpg" alt="My Image"]
To current one:
function handleShortcodes($content, $shortcodes){
function read_attr($attr) {
$atList = [];
if (preg_match_all('/\s*(?:([a-z0-9-]+)\s*=\s*"([^"]*)")|(?:\s+([a-z0-9-]+)(?=\s*|>|\s+[a..z0-9]+))/i', $attr, $m)) {
for ($i = 0; $i < count($m[0]); $i++) {
if ($m[3][$i])
$atList[$m[3][$i]] = null;
else
$atList[$m[1][$i]] = $m[2][$i];
}
}
return $atList;
}
//Loop through all shortcodes
foreach($shortcodes as $key => $function){
$dat = array();
preg_match_all("/\[".$key."(.*?)\]/", $content, $dat);
if(count($dat) > 0 && $dat[0] != array() && isset($dat[1])){
$i = 0;
$actual_string = $dat[0];
foreach($dat[1] as $temp){
$params = read_attr($temp);
$content = str_replace($actual_string[$i], $function($params), $content);
$i++;
}
}
}
return $content;
}
$content = '[image source="one" alt="one two"]';
Result:
array(
[source] => myimage.jpg,
[alt] => My Image
)
Updated (Feb 11, 2020)
It appears to be following regex under preg_match only identifies shortcode with attributes
preg_match_all("/\[".$key." (.+?)\]/", $content, $dat);
to make it work with as normal [contact-form] or [mynotes]. We can change the following to
preg_match_all("/\[".$key."(.*?)\]/", $content, $dat);
I just had the same problem. For what I have to do, I am going to take advantage of existing xml parsers instead of writing my own regex. I am sure there are cases where it won't work
example.php
<?php
$file_content = '[include file="header.html"]';
// convert the string into xml
$xml = str_replace("[", "<", str_replace("]", "/>", $file_content));
$doc = new SimpleXMLElement($xml);
echo "name: " . $doc->getName() . "\n";
foreach($doc->attributes() as $key => $value) {
echo "$key: $value\n";
}
$ php example.php
name: include
file: header.html
to make it work on ubuntu I think you have to do this
sudo apt-get install php-xml
(thanks https://drupal.stackexchange.com/a/218271)
If you have lots of these strings in a file, then I think you can still do the find replace, and then just treat it all like xml.

Parse url to get rid of all parameters after the first

From what I understand youtube.com uses three types of urls for their video links.
http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related
http://www.youtube.com/watch?v=8uLPtmCroQ8
http://youtu.be/8uLPtmCroQ8
I get this url submitted to my site in any one of these different ways and I store the url into a custom field called $video_code. I need to strip it of any parameters that come after the id of the video so if a user submit the first url above, &feature=related gets stripped. I'm using php.
If I understand your problem correctly, You could use something like this to store the video id in the databse and then construct the url as you like.
function getVideoId($url)
{
$parsedUrl = parse_url($url);
if ($parsedUrl === false)
return false;
if (!empty($parsedUrl['query']))
{
$query = array();
parse_str($parsedUrl['query'], $query);
if (!empty($query['v']))
return $query['v'];
}
if (in_array(strtolower($parsedUrl['host']), array('youtu.be', 'www.youtu.be')))
return trim($parsedUrl['path'], '/');
return false;
}
$input = array('http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related', 'http://www.youtube.com/watch?v=8uLPtmCroQ8', 'http://youtu.be/8uLPtmCroQ8');
foreach ($input as $url)
{
echo getVideoId($url) . PHP_EOL;
}
In which language did you want to this? If it is in PHP you should look at this.
You could also do a regular expressions to split the string. Take a look here: http://www.php.net/manual/en/function.preg-split.php
Use this code:
$arr=array(
'http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related',
'http://www.youtube.com/watch?v=8uLPtmCroQ8',
'http://youtu.be/8uLPtmCroQ8',
);
for($i=0; $i<count($arr); $i++){
$urlarr = parse_url($arr[$i]);
if (!empty($urlarr['query'])) {
parse_str($urlarr['query']);
$qarr = array();
if (!empty($v))
$qarr['v'] = $v;
$urlarr['query'] = http_build_query($qarr);
$arr[$i] = http_build_url('', $urlarr);
}
}
print_r($arr);
OUTPUT:
Array
(
[0] => http://www.youtube.com/watch?v=8uLPtmCroQ8
[1] => http://www.youtube.com/watch?v=8uLPtmCroQ8
[2] => http://youtu.be/8uLPtmCroQ8
)
function getVideoCode($url){
$videoCode;
$code_parse = parse_url($url);
if(empty($code_parse["query"])){
$videoCode = str_replace("/"," ",$code_parse["path"]);
}else{
$videoCode = clearQuery($code_parse["query"]);
}
echo $videoCode;
}
function clearQuery($query){
$redundant = array("v", "&", "feature","=","related");
return str_replace($redundant," ",$query);
}
It is not a professional code but It's easy to understand.When I call like this:
getVideoCode("http://youtu.be/8uLPtmCroQ8");
getVideoCode("http://www.youtube.com/watch?v=8uLPtmCroQ8");
getVideoCode("http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related");
The Output is
8uLPtmCroQ8
8uLPtmCroQ8
8uLPtmCroQ8

need advice on re-associating an array value with original key

I'm trying to write a program that will grab a bunch of images from a webpage and figure out which of the images is the largest.
So far I've taken the images, put them into an array, used the getimagesize() function to determine the heights. I then placed all of the heights into another array and sorted them in reverse order to get the largest one. So far so good.
My problem now is that I must find a way to re-associate the largest image with its initial image link. I've thought of potentially running the initial code to fetch the images again from the web page. Then comparing the 1st value in the array I've used to determine the biggest image with the images a second time, but this seems like a waste of bandwidth and I get a feeling there is an easier way to re-associate the height value with its initial image. Am I right?
<?php
$url = 'http://lockerz.com/s/104049300';
// Fetch page
$string = FetchPage($url);
// Regex that extracts the images (full tag)
$image_regex_src_url = '/<img[^>]*'.
'src=[\"|\'](.*)[\"|\']/Ui';
preg_match_all($image_regex_src_url, $string, $out, PREG_PATTERN_ORDER);
$img_tag_array = $out[0];
echo "<pre>"; print_r($img_tag_array); echo "</pre>";
// Regex for SRC Value
$image_regex_src_url = '/<img[^>]*'.
'src=[\"|\'](.*)[\"|\']/Ui';
preg_match_all($image_regex_src_url, $string, $out, PREG_PATTERN_ORDER);
$images_url_array = $out[1];
$image_heights_array = array();
foreach ($images_url_array as $imagelink)
{
if (substr($imagelink,0,7)=="http://")
{
$getheight = getimagesize($imagelink);
array_push($image_heights_array,"$getheight[1]");
}
}
rsort($image_heights_array);
echo "<pre>"; print_r($image_heights_array); echo "</pre>";
// Fetch Page Function
function FetchPage($path)
{
$file = fopen($path, "r");
if (!$file)
{
exit("The was a connection error!");
}
$data = '';
while (!feof($file))
{
// Extract the data from the file / url
$data .= fgets($file, 1024);
}
return $data;
}
?>
First off:
// Regex that extracts the images (full tag)
$image_regex_src_url = '/<img[^>]*'.
'src=[\"|\'](.*)[\"|\']/Ui';
preg_match_all($image_regex_src_url, $string, $out, PREG_PATTERN_ORDER);
$img_tag_array = $out[0];
echo "<pre>"; print_r($img_tag_array); echo "</pre>";
// Regex for SRC Value
$image_regex_src_url = '/<img[^>]*'.
'src=[\"|\'](.*)[\"|\']/Ui';
preg_match_all($image_regex_src_url, $string, $out, PREG_PATTERN_ORDER);
HTML parsing regex ewww. Let's simplify this... with an HTML parser.
<?php
// EDIT: Use a custom function to do the
// reverse of SORT_NUMERIC with asort
function height_compare($a, $b)
{
if ($a == $b) {
return 0;
}
return ($a > $b) ? -1 : 1;
}
$url = 'http://lockerz.com/s/104049300';
$doc = new DOMDocument();
// Okay this is HTML is kind of screwy
// So we're going to supress errors
#$doc->loadHTMLFile($url);
// Get all images
$images_list = $doc->getElementsByTagName('img');
$images = array();
foreach($images_list as $image) {
// Get the src attribute
$image_source = $image->getAttribute('src');
$image_size_info = getimagesize($image_source);
$images[$image_source] = $image_size_info[1];
}
// Do a numeric sort on the height
uasort($images, "height_compare");
print_r($images);
?>
Much shorter and more readable. The result:
$ php test.php
Array
(
[http://c0013784.cdn1.cloudfiles.rackspacecloud.com/x2_633aa94] => 328
[http://ad.doubleclick.net/ad/buz.plixi/photos;pos=300a;celeb=;kw=;tile=2;sz=300x250,300x600;ord=123456789?] => 250
[http://static.lockerz.com/pegasus/images/video_thumb.jpg?1.0.0] => 207
[http://static.lockerz.com/pegasus/images/plixi-banner.png?1.0.0] => 107
[http://ad.doubleclick.net/ad/buz.plixi/photos;pos=728a;celeb=;kw=;tile=1;sz=728x90;ord=123456789?] => 90
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636f30c] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_637676e] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_63735a0] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636e73c] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_63795d0] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636a2c7] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636bf79] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636ca08] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636e419] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_636deca] => 79
[http://c0013787.cdn1.cloudfiles.rackspacecloud.com/x2_6384277] => 79
Keep sizes and URLs in one array and use usort to sort multidimensional array.
$images_url_array = $out[1];
$images = array();
foreach ($images_url_array as $imagelink)
{
if (substr($imagelink, 0, 7)=="http://")
{
$getheight = getimagesize($imagelink);
$images[] = array('height' => $getheight[1], 'url' => $imagelink);
}
}
usort($images, function ($a, $b)
{
if ($a['height'] > $b['height']) return 1;
elseif ($a['height'] < $b['height']) return -1;
else return 0;
});
I don't know PHP so I can't help you with the code, but maybe you could try this idea. Have the first array store an ImageObject. This class to have three properties, imagesize, id, and src.
You can go through the first array, find the imagesize and then sort it by biggest size. Use the id to get individual objects.
if you use arsort() the array keys will be preserved, then you can reset() the array pointer to start of the array, and get the first key().
But you will also need to preserve the same keys across the images_url_array and image_height_array
foreach ($images_url_array as $key => $imagelink)
{
if (substr($imagelink,0,7)=="http://")
{
$getheight = getimagesize($imagelink);
$image_heights_array[$key] = $getheight[1];
}
}
//...
rsort($image_heights_array);
reset($image_heights_array);
$largest_image_key = key($image_heights_array);
$largest_image_url = $images_url_array[$key];

Categories