if finding element with phpsimpledom failed - php

I am using simplephpdom For finding the title of one speciall page like this :
function get_title_with_dom($url) {
$amounts = array();
$html = file_get_html($url);
$elements = $html->find('title');
return trim($elements[0]->innertext);
}
So, now there is a problem for the pages that does NOT have title !
I will get this error :
Fatal error: Call to a member function find() on a non-object in ...
So, HOW can i say, if could not find element , then return NULL or FALSE ?
I tried to use such this blow function , but it doesn't work (work like code above) :
function get_title_with_dom($url) {
$amounts = array();
$html = file_get_html($url);
if (!($html->find('title'))) {
return false;
} else {
$elements = $html->find('title');
return trim($elements[0]->innertext);
}
}

You don't need both str_get_html and file_get_html. If you're feeding the url just use file_get_html.
function get_title_with_dom($url) {
$data = false;
$html = file_get_html($url);
$title = $html->find('title', 0);
if($title) {
$data = $title->innertext;
}
return $data;
}
var_dump(get_title_with_dom('http://www.google.com')); // Google
var_dump(get_title_with_dom('http://codepad.viper-7.com/moj97E')); // bool(false)

Related

Undefined property: stdClass: - What is wrong?

I get some data externally but gets this error because the variable is "empty":
Undefined property: stdClass::$summary in /Applications/MAMP/htdocs/jobportal/functions.php on line 68
I have tried to build a function to help me:
$summary = convert_empty($user->summary);
function convert_empty($data) {
if(isset($data)) {
return $data;
} else {
return ".";
}
}
But the error is still there. I have tried isset, empty, and defined. I think I miss another point here - since none of it is working.
That means that the object $user doesn't have a summary member variable defined.
$summary = isset($user->summary) ? convert_empty($user->summary) : NULL;
Or
$summary = isset($user->summary) ? convert_empty(isset($user->summary) ? $user->summary : NULL);
Now you won't see the warning and $summary will be set to NULL, assuming that you're expecting $summary to be NULL in this situation in which $user->summary is undefined.
The second one allows your convert_empty to figure it out.
The issue is not in your function, but how you call it. The error is that you're trying to access ->summary but doesn't exists. You could use something like this:
$summary = convert_empty($user, 'summary');
function convert_empty($data, $key) {
if (isset($data->$key))
return $data->$key;
return ".";
}
Note that you should also test if $data is an object too.
if (is_object($data) && isset($data->$key)) { ... }
Or, without a function using conditional ternary operator :
$summary = isset($user->summary) ? $user->summary : '.';
EDIT for a deeper use :
convert_empty($user, 'positions', 'values', $i, 'title');
function convert_empty($obj) {
$error = '.';
$args = func_get_args();
array_shift($args); // remove $obj
$ref = $obj ;
foreach ($args as $arg) {
if (is_array($ref)) {
if (!isset($ref[$arg])) return $error ;
$ref = $ref[$arg] ;
}
elseif (is_object($ref)) {
if (!isset($ref->$arg)) return $error ;
$ref = $ref->$arg ;
}
}
return $ref ;
}

Find Word Which comes first in php

I have 2 words like %sku% and %any% that will be used in the sites url structure.
This data will be saved in a database and I need to find out which comes first.
E.g.
In the below url %sku% comes first
http://example.com/%sku%/product/%any%
While in the below url %any% comes first
http://example.com/%any%/product/%sku%
Furthermore I cant be sure that the structure will be consistent it could be like any of the below:
http://example.com/%sku%/product/%any%
http://example.com/%any%/product/%sku%
http://example.com/%any%/%sku%
http://example.com/product/%sku%
http://example.com/product/%any%
I want to check which comes first and which comes last.. but %sku% and%any%` are defined by me.. so i can be 100% sure that those tags are going to be used.
The following code will return the first and last occurring items from a designated $attributes array.
$string = 'http://example.com/%sku%/product/%any%';
// values to check for
$attributes = ['%sku%', '%any%'];
$results = array();
foreach($attributes as $attribute)
{
// Get position of attribute in uri string
$pos = strpos($string, $attribute);
// if it exists we add it to the array with the position
if($pos)
{
$results[$attribute] = $pos;
}
}
// Get the first occuring attribute
$firstOccuringAttribute = array_search( min($results), $results);
// Get the last occuring attribute
$lastOccuringAttribute = array_search( max($results), $results);
This could be refactored into something a bit more readable:
$uri = 'http://example.com/%sku%/product/%any%';
$attributes = ['%sku%', '%any%'];
$lastAttribute = getLastAttribute($uri, $attributes);
$firstAttribute = getFirstAttribtue($uri, $attributes);
function getAttributeWeighting($uri, $attributes)
{
$results = array();
foreach($attributes as $attribute)
{
$pos = strpos($uri, $attribute);
if($pos)
{
$results[$attribute] = $pos;
}
}
return $results;
}
function getFirstAttribute($uri, $attributes)
{
$attributeWeighting = getAttributeWeighting($uri, $attributes);
return array_search( min($attributeWeighting), $attributeWeighting);
}
function getLastAttribute($uri, $attributes)
{
$attributeWeighting = getAttributeWeighting($uri, $attributes);
return array_search( max($attributeWeighting), $attributeWeighting);
}
Just use strpos
something like:
$URL = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$posOfSku=strlen($URL);
$posOfAny=strlen($URL);
if(strpos($URL ,'%sku%') !== false) {
$posOfSku = strpos($URL ,'%sku%');
}
if(strpos($URL ,'%any%') !== false) {
$posOfAny= strpos($URL ,'%any%');
}
$result = ($posOfAny < $posOfSku) ? 'any came 1st' : 'sku came 1st';
echo $result;

How to download STANDARD-XML metadata from RETS using PHRETS

Is there any solution to download STANDARD-XML metadata from RETS using PHRETS?
Currently am able to extract each class metadata as an array using PHRETS function GetMetadataTable and combining & converting to XML format.
But then recently I found difference in single STANDARD-XML metadata(of entire resources and classes) and individual class metadata. Using metadata viewer service RETSMD.com(built on PHRETS) also, the class name getting from STANDARD-XML metadata is different and unable to view the details.
Note: I got the STANDARD-XML metadata via direct browser log-in using credentials, like this
http://rets.login.url/GetMetadata?Type=METADATA-TABLE&Format=STANDARD-XML&ID=0
Anyone faced the same? Is there any solution using PHP?
Thanks in Advance!
I got a solution by modifying PHRETS library.
Added a new function there with following code,
if (empty($this->capability_url['GetMetadata'])) {
die("GetServerInformation() called but unable to find GetMetadata location. Failed login?\n");
}
$optional_params['Type'] = 'METADATA-SYSTEM';
$optional_params['ID'] = '*';
$optional_params['Format'] = 'STANDARD-XML';
//request server information
$result = $this->RETSRequest($this->capability_url['GetMetadata'], $optional_params );
if (!$result) {
return false;
}
list($headers, $body) = $result;
$xml = $this->ParseXMLResponse($body);
Note: Main thing to note is,
$optional_params['ID'] = '*';
Should be '*' instead '0'
If anyone is still unable to retrieve STANDARD-XML data from the CREA DDF data feed using PhRETS v2.x.x, I created a fork to the ./src/Parsers/Search/OneX.php file. You can add the following protected methods to the end of the file:
protected function parseDDFStandardXMLData(&$xml)
{
// we can only work with an array
$property_details = json_decode(json_encode($xml), true);
$retn = array();
if(! empty($property_details['RETS-RESPONSE']['PropertyDetails'])) {
foreach($property_details['RETS-RESPONSE']['PropertyDetails'] as $property_array) {
$retn[] = $this->parseArrayElements(null, $property_array);
}
}
return $retn;
}
protected function parseArrayElements($parent_key, $element)
{
// three possible $element types
// 1. scalar value
// 2. sub-array
// 3. SimpleXMLElement Object
$retn = array();
if(is_object($element)) {
$element = json_decode(json_encode($element), true);
}
if(is_array($element)) {
foreach($element as $node_key => $node) {
$key = $node_key;
if(! empty($parent_key)) {
$key = $parent_key . '|' . $key;
}
if(is_array($node) || is_object($node)) {
$nodes = $this->parseArrayElements($key, $node);
if(!empty($nodes)) {
foreach($nodes as $k => $n) {
$retn[$k] = $n;
}
}
}else{
$retn[$key] = $node;
}
}
}else{
$retn[$parent_key] = $element;
}
return $retn;
}
protected function parseRecordFromArray(&$array, Results $rs)
{
$r = new Record;
foreach($rs->getHeaders() as $key => $name) {
$r->set($name, $array[$name]);
}
return $r;
}
Then replace the parseRecords() method with:
protected function parseRecords(Session $rets, &$xml, $parameters, Results $rs)
{
if (isset($xml->DATA)) {
foreach ($xml->DATA as $line) {
$rs->addRecord($this->parseRecordFromLine($rets, $xml, $parameters, $line, $rs));
}
}elseif (isset($xml->{"RETS-RESPONSE"}->PropertyDetails)) {
$data = $this->parseDDFStandardXMLData($xml);
if(! empty($data)) {
$fields_saved = false;
foreach ($data as $line) {
if(!$fields_saved) {
$rs->setHeaders(array_keys($line));
}
$rs->addRecord($this->parseRecordFromArray($line, $rs));
}
}
}
}
The line, }elseif (isset($xml->{"RETS-RESPONSE"}->PropertyDetails)) { in the latter method does the trick to identify the STANDARD-XML RETS-RESPONSE node and parse the data.
Hope this helps,
Cheers!

PHP Poppler implementation failure

I am currently using this library https://github.com/php-poppler/php-poppler in addition to Poppler in order to convert PDF files to HTML. I installed the library via composer and unfortunately there is no documentation available except some guides about installation but still incomplete.
Given that this Main API usage:
$file = new Poppler\Process\PdfFile(...);
// Get pdf info
print_r($file->getInfo('test.pdf'));
// Get text content of pdf
echo $file->toText('test.pdf');
// Transform to html
$file->toHtml('test.pdf', '/path/for/html');
I can not even define what parameters should be given in $file = new Poppler\Process\PdfFile(...);
What I have tried:
<?php
include 'vendor/autoload.php';
use Poppler\Processor\PdfFile;
use Poppler\Driver\Pdfinfo;
use Poppler\Driver\Pdftohtml;
use Poppler\Driver\Pdftotext;
$a = new Pdfinfo;
$b = new Pdftohtml;
$c = new Pdftotext;
$file = new PdfFile($a,$b,$c);
print_r($file->getInfo('test.pdf'));
echo $file->toText('test.pdf');
$file->toHtml('test.pdf', 'Results');
?>
This gives an error:
Catchable fatal error: Argument 1 passed to Alchemy\BinaryDriver\AbstractBinary::__construct() must be an instance of Alchemy\BinaryDriver\ProcessBuilderFactoryInterface, none given
Here's PdfFile.php:
<?php
namespace Poppler\Processor;
use Poppler\Driver\Pdfinfo;
use Poppler\Driver\Pdftohtml;
use Poppler\Driver\Pdftotext;
use Poppler\Exception\FileNotFoundException;
class PdfFile
{
private $pdfinfo;
private $pdftotext;
private $pdftohtml;
public function __construct(Pdfinfo $pdfinfo, Pdftotext $pdftotext, Pdftohtml $pdftohtml)
{
$this->pdfinfo = $pdfinfo;
$this->pdftotext = $pdftotext;
$this->pdftohtml = $pdftohtml;
}
public function toText($inputfile, $toEncoding = 'UTF-8')
{
if (!file_exists($inputfile)) {
throw new FileNotFoundException("File $inputfile not found.");
}
$output = $this->pdftotext->command(array('-nopgbrk', $inputfile, '-'));
$fromEncoding = mb_detect_encoding($output);
if ($fromEncoding) {
return mb_convert_encoding($output, $toEncoding, $fromEncoding);
}
return mb_convert_encoding($output, $toEncoding);
}
public function toHtml($inputfile, $outputfile)
{
if (!file_exists($inputfile)) {
throw new FileNotFoundException("File $inputfile not found.");
}
$output = $this->pdftohtml->command(array($inputfile, $outputfile));
return $output;
}
public function getInfo($inputfile)
{
if (!file_exists($inputfile)) {
throw new FileNotFoundException("File $inputfile not found.");
}
$args = array($inputfile);
$output = $this->pdfinfo->command($args);
$info = array();
foreach (explode(PHP_EOL, $output) as $line) {
if (strpos($line, ': ') === false) {
continue;
}
$parts = explode(': ', $line);
$key = trim($parts[0]);
$value = trim($parts[1]);
$info[$key] = $value;
}
return $info;
}
}

Access multidimensional array with a path-like string

I have a function called get_config() and an array called $config.
I call the function by using get_config('site.name') and am looking for a way to return the value of $config so for this example, the function should return $config['site']['name'].
I'm nearly pulling my hair out - trying not to use eval()! Any ideas?
EDIT: So far I have:
function get_config($item)
{
global $config;
$item_config = '';
$item_path = '';
foreach(explode('.', $item) as $item_part)
{
$item_path .= $item."][";
$item = $config.{rtrim($item_path, "][")};
}
return $item;
}
This should work:
function get_config($config, $string) {
$keys = explode('.', $string);
$current = $config;
foreach($keys as $key) {
if(!is_array($current) || !array_key_exists($key, $current)) {
throw new Exception('index ' . $string . ' was not found');
}
$current = $current[$key];
}
return $current;
}
you could try something like...
function get_config($item)
{
global $config;
return $config[{str_replace('.','][',$item)}];
}
Inside your get_config function, you can parse the string using explode function in php
function get_config($data){
$pieces = explode(".", $data);
return $config[$pieces[0]][$pieces[1]];
}

Categories