Ignore parts of URL - php

I'm working on a simple script to scrape the channel ID of a YouTube URL.
For example, to get the channel ID on this URL:
$url = 'https://youtube.com/channel/UCBLAoqCQyz6a0OvwXWzKZag';
I use regex:
preg_match( '/\/channel\/(([^\/])+?)$/', $url, $matches );
Works fine. But if the URL has any extra parameters or anything else after the channel ID, it doesn't work. Example:
https://youtube.com/channel/UCBLAoqCQyz6a0OvwXWzKZag?PARAMETER=HELLO
https://youtube.com/channel/UCBLAoqCQyz6a0OvwXWzKZag/RANDOMFOLDER
etc...
My question is, how can I adjust my regex so it works with those URLs? We don't want to match with the random parameters etc
Feel free to test my ideone code.

You can fix the regexps in the following way:
$preg_entities = [
'channel_id' => '\/channel\/([^\/?#]+)', //match YouTube channel ID from url
'user' => '\/user\/([^\/?#]+)', //match YouTube user from url
];
See the PHP demo.
With [^\/?#]+ patterns, the regex won't go through the query string in an URL, and you will get clear values in the output.
Full code snippet:
function getYouTubeXMLUrl( $url) {
$xml_youtube_url_base = 'h'.'ttps://youtube.com/feeds/videos.xml';
$preg_entities = [
'channel_id' => '\/channel\/([^\/?#]+)', //match YouTube channel ID from url
'user' => '\/user\/([^\/?#]+)', //match YouTube user from url
];
foreach ( $preg_entities as $key => $preg_entity ) {
if ( preg_match( '/' . $preg_entity . '/', $url, $matches ) ) {
if ( isset( $matches[1] ) ) {
return [
'rss' => $xml_youtube_url_base . '?' . $key . '=' . $matches[1],
'id' => $matches[1],
'type' => $key,
];
}
}
}
}
Test:
$url = 'https://youtube.com/channel/UCBLAoqCQyz6a0OvwXWzKZag?PARAMETER=HELLO';
print_r(getYouTubeXMLUrl($url));
// => Array( [rss] => https://youtube.com/feeds/videos.xml?channel_id=UCBLAoqCQyz6a0OvwXWzKZag [id] => UCBLAoqCQyz6a0OvwXWzKZag [type] => channel_id )
$url = 'https://youtube.com/channel/UCBLAoqCQyz6a0OvwXWzKZag/RANDOMFOLDER';
print_r(getYouTubeXMLUrl($url));
// => Array( [rss] => https://youtube.com/feeds/videos.xml?channel_id=UCBLAoqCQyz6a0OvwXWzKZag [id] => UCBLAoqCQyz6a0OvwXWzKZag [type] => channel_id )

Related

PHP - processing array values

I have an array that contains DNS records and looks like this
Array ( [domain] => xxxx.com [record_id_+++711753] => 711753 [host_+++711753] => # [type_+++711753] => A [priority_+++711753] => [value_+++711753] => 80.82.72.12 [record_id_+++711752] => 711752 [host_+++711752] => www [type_+++711752] => A [priority_+++711752] => [value_+++711752] => 80.82.72.12 [record_id_+++711754] => 711754 [host_+++711754] => # [type_+++711754] => MX [priority_+++711754] => 20 [value_+++711754] => fallback.denit.net [record_id_+++711755] => 711755 [host_+++711755] => # [type_+++711755] => MX [priority_+++711755] => 10 [value_+++711755] => ms.denit.net [record_id_+++711756] => 711756 [host_+++711756] => mail [type_+++711756] => A [priority_+++711756] => [value_+++711756] => 62.148.185.22 [record_id_+++711757] => 711757 [host_+++711757] => autodiscover [type_+++711757] => CNAME [priority_+++711757] => [value_+++711757] => autoredirect.mshex.nl [record_id_+++1148031] => 1148031 [host_+++1148031] => webmail [type_+++1148031] => CNAME [priority_+++1148031] => [value_+++1148031] => webmail.mshex.nl )
_+++ is a delimiter between the record_id and the type of DNS value.
I need to talk to an API to update records. It works like this (example);
$mdr->addParam( "command", "dns_record_modify" );
$mdr->addParam( "domein", "xxx" );
$mdr->addParam( "tld", "com" );
$mdr->addParam( "record_id", "461741" );
$mdr->addParam( "host", "#" );
$mdr->addParam( "address", "mail2.xxx.com" );
$mdr->addParam( "priority", "20" );
I know that I can use explode to fill the API values, domain and TLD.
However I cant seem to find a way to group the array values by record_id and fire a request per record_id that combines multiple values like host, type and priority.
How should I achieve this?
You're correct about using the explode() method. IMO this is the best approach to the solution. I updated the answer because of the slight typo error and also added a working version. See it here.
# loop each entry
foreach($array as $key => $value)
{
# [0] - record_id
# [1] / $value - 711753
# check that the key isn't domain since it doesn't contain _++
if($key != 'domain')
{
$mdr->addParam(explode('_+++', $key)[0], $value);
}
else
{
$mdr->addParam($key,$value);
}
}
The above code snippet explodes the _+++ out of the key to find the callback value. The $value then holds the corresponding data callback and then each is passed through your instanced object in the method addParam().
Since the callback domain in your array keys does not contain the _+++ brace, I did a check before using the explode() method.
To group the array values by record_ids, you could create a new, multidimensional array and use the record IDs as top-level keys. Here's an example:
$data = array();
$data['domain'] = 'xxxx.com';
$data['record_id_+++711753'] = 711753;
$data['host_+++711753'] = '#';
$data['type_+++711753'] = 'A';
$data['type_+++1148031'] = 'CNAME';
$data['host_+++1148031'] = 'webmail';
$sorted_data = [];
foreach($data as $key=>$val){
$key_info = explode('_+++', $key);
if (count($key_info) > 1){
$record_id = $key_info[1];
$key_name = $key_info[0];
$sorted_data[$record_id][$key_name] = $val;
}
}
var_dump($sorted_data);
You could transform your data to another structure, and then produce the $mdr->addParam calls from that:
$domain = $data["domain"]; // "xxx.com"
$tld = end(explode(".", $domain)) "com"
$domain = substr($domain, count($domain)-count($tld)-1); // "xxx"
$updates = [];
foreach ($data as $key => $value) {
$parts = explode("_+++", $key);
if (count($parts) != 2) continue;
list($key, $rec) = $parts;
if ($key == "value") $key = "address";
$updates[$rec][$key] = $value;
}
$updates will be something like this:
Array(
[711753] => Array (
[record_id] => 711753
[host] => #
[type] => A
[priority] =>
[address] => 80.82.72.12
),
[711752] => Array (
[record_id] => 711752
[host] => www
[type] => A
[priority] =>
[address] => 80.82.72.12
),
...
Then from that, you continue:
foreach($updates as $update) {
$mdr = new .... // some code to create new instance
$mdr->addParam( "command", "dns_record_modify");
$mdr->addParam( "domein", $domain);
$mdr->addParam( "tld", $tld);
foreach($update as $key => $value) {
$mdr->addParam($key, $value);
}
// execute mdr ...
}

Create shortcode with parameter in PHP Joomla

I've created a simple shortcode plugin on Joomla.
Actually I am trying to integrate Cleeng Video with Joomla. And will connect it's users in the future ( I hope ).
I've stack on creating shortcode's parameter. I don't know how to parse it's parameter and value.
My Shortcode is here (no parameter)
{cleengvideo}<iframe class="wistia_embed" src="http://fast.wistia.net/embed/iframe/5r8r9ib6di" name="wistia_embed" width="640" height="360" frameborder="0" scrolling="no" allowfullscreen=""></iframe>{/cleengvideo}
My code is here
public function onContentPrepare($content, $article, $params, $limit) {
preg_match_all('/{cleengvideo}(.*?){\/cleengvideo}/is', $article->text, $matches);
$i = 0;
foreach ($matches[0] as $match) {
$videoCode = $matches[1][$i];
$article->text = str_replace($match, $videoCode, $article->text);
}
I want to set height, width and 5r8r9ib6di this code from shortcode at least.
Please can anyone help me with adding and parsing it's parameter
To get a parameter, you can simply use the following code:
$params->get('param_name', 'default_value');
So for example, in your XML file, if you had a field like so:
<field name="width" type="text" label="Width" default="60px" />
you would call the parameter like so:
$params->get('width', '60px');
Note that you don't have to add the default value as the second string, however I always find it good practice.
Hope this helps
I think I could found it's solution.
It's here https://github.com/Cleeng/cleeng-wp-plugin/blob/master/php/classes/Frontend.php
Code is
$expr = '/\[cleeng_content(.*?[^\\\])\](.*?[^\\\])\[\/cleeng_content\]/is';
preg_match_all( $expr, $post->post_content, $m );
foreach ( $m[0] as $key => $content ) {
$paramLine = $m[1][$key];
$expr = '/(\w+)\s*=\s*(?:\"|")(.*?)(?<!\\\)(?:\"|")/si';
preg_match_all( $expr, $paramLine, $mm );
if ( ! isset( $mm[0] ) || ! count( $mm[0] ) ) {
continue;
}
$params = array( );
foreach ( $mm[1] as $key => $paramName ) {
$params[$paramName] = $mm[2][$key];
}
if ( ! isset( $params['id'] ) ) {
continue;
}
$content = array(
'contentId' => $params['id'],
'shortDescription' => #$params['description'],
'price' => #$params['price'],
'itemType' => 'article',
'purchased' => false,
'shortUrl' => '',
'referred' => false,
'referralProgramEnabled' => false,
'referralRate' => 0,
'rated' => false,
'publisherId' => '000000000',
'publisherName' => '',
'averageRating' => 4,
'canVote' => false,
'currencySymbol' => '',
'sync' => false
);
if ( isset( $params['referral'] ) ) {
$content['referralProgramEnabled'] = true;
$content['referralRate'] = $params['referral'];
}
if ( isset( $params['ls'] ) && isset( $params['le'] ) ) {
$content['hasLayerDates'] = true;
$content['layerStartDate'] = $params['ls'];
$content['layerEndDate'] = $params['le'];
}
$this->cleeng_content[$params['id']] = $content;
}
Hope this helps someone searching for shortcode parameters, for parameters in short code we can use preg_match_all like that
preg_match_all('/{cleengvideo(.*?)}(.*?){\/cleengvideo}/is', $article->text, $matches);
This will give a array with 3 array elements, the second array have the parameters which you can maupulate with codes.
Hope this helps.

Magento: improving search engine (inflections, irrelevant words removal, etc.)

I'm interested in knowing if I can detect inflections (e.g. dogs/dog), remove non-important words ("made in the usa" -> "in" and "the" are not important), etc. in the search string entered by the user for the Magento search engine without hard-coding such many scenarios in one big PHP code block. I can process this search string to a certain degree, but it will look unsanitary and ugly.
Any suggestions or pointers for making it an "intelliegent" search engine?
Use this class:
class Inflection
{
static $plural = array(
'/(quiz)$/i' => "$1zes",
'/^(ox)$/i' => "$1en",
'/([m|l])ouse$/i' => "$1ice",
'/(matr|vert|ind)ix|ex$/i' => "$1ices",
'/(x|ch|ss|sh)$/i' => "$1es",
'/([^aeiouy]|qu)y$/i' => "$1ies",
'/(hive)$/i' => "$1s",
'/(?:([^f])fe|([lr])f)$/i' => "$1$2ves",
'/(shea|lea|loa|thie)f$/i' => "$1ves",
'/sis$/i' => "ses",
'/([ti])um$/i' => "$1a",
'/(tomat|potat|ech|her|vet)o$/i'=> "$1oes",
'/(bu)s$/i' => "$1ses",
'/(alias)$/i' => "$1es",
'/(octop)us$/i' => "$1i",
'/(ax|test)is$/i' => "$1es",
'/(us)$/i' => "$1es",
'/s$/i' => "s",
'/$/' => "s"
);
static $singular = array(
'/(quiz)zes$/i' => "$1",
'/(matr)ices$/i' => "$1ix",
'/(vert|ind)ices$/i' => "$1ex",
'/^(ox)en$/i' => "$1",
'/(alias)es$/i' => "$1",
'/(octop|vir)i$/i' => "$1us",
'/(cris|ax|test)es$/i' => "$1is",
'/(shoe)s$/i' => "$1",
'/(o)es$/i' => "$1",
'/(bus)es$/i' => "$1",
'/([m|l])ice$/i' => "$1ouse",
'/(x|ch|ss|sh)es$/i' => "$1",
'/(m)ovies$/i' => "$1ovie",
'/(s)eries$/i' => "$1eries",
'/([^aeiouy]|qu)ies$/i' => "$1y",
'/([lr])ves$/i' => "$1f",
'/(tive)s$/i' => "$1",
'/(hive)s$/i' => "$1",
'/(li|wi|kni)ves$/i' => "$1fe",
'/(shea|loa|lea|thie)ves$/i'=> "$1f",
'/(^analy)ses$/i' => "$1sis",
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => "$1$2sis",
'/([ti])a$/i' => "$1um",
'/(n)ews$/i' => "$1ews",
'/(h|bl)ouses$/i' => "$1ouse",
'/(corpse)s$/i' => "$1",
'/(us)es$/i' => "$1",
'/s$/i' => ""
);
static $irregular = array(
'move' => 'moves',
'foot' => 'feet',
'goose' => 'geese',
'sex' => 'sexes',
'child' => 'children',
'man' => 'men',
'tooth' => 'teeth',
'person' => 'people',
'admin' => 'admin'
);
static $uncountable = array(
'sheep',
'fish',
'deer',
'series',
'species',
'money',
'rice',
'information',
'equipment'
);
public static function pluralize( $string )
{
global $irregularWords;
// save some time in the case that singular and plural are the same
if ( in_array( strtolower( $string ), self::$uncountable ) )
return $string;
// check for irregular singular forms
foreach ( $irregularWords as $pattern => $result )
{
$pattern = '/' . $pattern . '$/i';
if ( preg_match( $pattern, $string ) )
return preg_replace( $pattern, $result, $string);
}
// check for irregular singular forms
foreach ( self::$irregular as $pattern => $result )
{
$pattern = '/' . $pattern . '$/i';
if ( preg_match( $pattern, $string ) )
return preg_replace( $pattern, $result, $string);
}
// check for matches using regular expressions
foreach ( self::$plural as $pattern => $result )
{
if ( preg_match( $pattern, $string ) )
return preg_replace( $pattern, $result, $string );
}
return $string;
}
public static function singularize( $string )
{
global $irregularWords;
// save some time in the case that singular and plural are the same
if ( in_array( strtolower( $string ), self::$uncountable ) )
return $string;
// check for irregular words
foreach ( $irregularWords as $result => $pattern )
{
$pattern = '/' . $pattern . '$/i';
if ( preg_match( $pattern, $string ) )
return preg_replace( $pattern, $result, $string);
}
// check for irregular plural forms
foreach ( self::$irregular as $result => $pattern )
{
$pattern = '/' . $pattern . '$/i';
if ( preg_match( $pattern, $string ) )
return preg_replace( $pattern, $result, $string);
}
// check for matches using regular expressions
foreach ( self::$singular as $pattern => $result )
{
if ( preg_match( $pattern, $string ) )
return preg_replace( $pattern, $result, $string );
}
return $string;
}
public static function pluralize_if($count, $string)
{
if ($count == 1)
return "1 $string";
else
return $count . " " . self::pluralize($string);
}
}
And if you have a time use a standard way for inflection usage: http://en.wikipedia.org/wiki/Inflection
You can as array combine with XML so put all inflections data, look at how codeigniter has inflection very friendly: http://ellislab.com/codeigniter/user-guide/helpers/inflector_helper.html
Many frameworks supports built-in inflections but it will focus only in mainly English only. For other languages you should write own... or use unicode.org with some inflections standards for other languages if you need it.

Generate URL with parameters from an array

I need to take an array like I have below:
$subids = Array
(
[s1] => one
[s2] => two
[s3] => three
[s4] => four
[s5] => five
[s6] => six
)
and generate a URL such as http://example.com?s1=one&s2=two&s3=three=&s4=four&s5=five&s6=six
All of the subids are not always defined, so sometimes s3 may not be defined, so it shouldn't be appended to the URL. Additionally, whatever the first subid is, it has to have the ? preceding it instead of the ampersand (&)
So if the array is just:
$subids = Array
(
[s2] => two
[s6] => six
)
then the URL needs to be http://example.com?s2=two&s6=six
I have the following so far:
$url = 'http://example.com'
foreach ($subids AS $key => $value) {
$result[$id]['url'] .= '&' . $key . '=' . $value;
}
However, I'm not sure what the best way would be to append the ? at the beginning of the first key/value pair.
I feel like there's a PHP function to help with this but I'm not finding much. I'm using Codeigniter if there's anything I can use that is provided by CI.
All you need is http_build_query:
$final = $url . "?" . http_build_query($subids);
You can use with http_build_query() function.
Example from php.net:
<?php
$data = array(
'foo' => 'bar',
'baz' => 'boom',
'cow' => 'milk',
'php' => 'hypertext processor',
);
echo http_build_query( $data ) . "\n";
echo http_build_query( $data, '', '&' );
?>
And output this lines:
foo=bar&baz=boom&cow=milk&php=hypertext+processor
foo=bar&baz=boom&cow=milk&php=hypertext+processor
You can read from the source: http://www.php.net/manual/en/function.http-build-query.php
BTW, If you use with WordPress, you can this function: http://codex.wordpress.org/Function_Reference/add_query_arg
Have fun. :)
You can use http_build_query() function but be sure to do some validations if the url comes from an external function for example.
$url = getUrlSomewhere();
$params = ['param' => 'value', 'param2' => 'value2'];
$queryParams = http_build_query($params);
if (strpos($url, '?') !== FALSE) {
$url .= '&'. $queryParams;
} else {
$url .= '?'. $queryParams;
}
If you have PECL extension you can use http_build_url() which already takes into account if you are adding more parameters to a pre-existent URL or not among other validations it does.

file_get_contents not saving to an array

I have a section in my code which uses file_get_contents to grab the url from the given web page. I also have a section in my code which scans the titles in each link value in my array.
I want end up having an array similar to this :
Array(
Google => array(
[title] => Google
[link] => http://www.google.com
)
)
but no values are saved to my array, even though i can't detect any errors
$links = Array();
$URL = 'http://www.theqlick.com'; // change it for urls to grab
$file = file_get_contents($URL);
// grabs the urls from URL
if( strlen( $file )>0 ) {
$links[] = preg_match_all( "/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/", $file, $links);
}
function Titles() {
global $links;
$str = implode('',array_map('file_get_contents',$links));
error_reporting(E_ERROR | E_PARSE);
$titles = Array();
if( strlen( $str )>0 ) {
$titles[] = preg_match_all( "/\<title\>(.*)\<\/title\>/", $str, $title );
return $title;
return $links;
}
}
$newArray = array();
$j = 0;
foreach( $links as $key => $val ){
$newArray[$key] = array( 'link' => $val, 'title' => $title[1][$j++]);
}
print_r($newArray);
The following code does not seem to return anything
$links[] = preg_match_all( "/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/", $file, $links);
Try the following
$links = Array();
$URL = 'http://www.theqlick.com'; // change it for urls to grab
$file = file_get_contents($URL);
// grabs the urls from URL
if (strlen($file) > 0) {
$links[] = preg_match_all('#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $file, $links);
}
var_dump($links);
Output
array
0 =>
array
0 => string 'http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd' (length=55)
1 => string 'http://www.w3.org/1999/xhtml' (length=28)
2 => string 'http://www.theqlick.com' (length=23)
3 => string 'http://www.theqlick.com' (length=23)
1 =>
array
0 => string 'd' (length=1)
1 => string 'l' (length=1)
2 => string 'm' (length=1)
3 => string 'm' (length=1)
2 => int 4

Categories