I have this PHP class for generate dynamic xml sitemap:
class::
namespace SitemapPHP;
class Sitemap {
/**
*
* #var \XMLWriter
*/
private $writer;
private $domain;
private $path;
private $filename = 'sitemap';
private $current_item = 0;
private $current_sitemap = 0;
const EXT = '.xml';
const SCHEMA = 'http://www.sitemaps.org/schemas/sitemap/0.9';
const DEFAULT_PRIORITY = 0.5;
const ITEM_PER_SITEMAP = 50000;
const SEPERATOR = '-';
const INDEX_SUFFIX = 'index';
/**
*
* #param string $domain
*/
public function __construct($domain) {
$this->setDomain($domain);
}
/**
* Sets root path of the website, starting with http:// or https://
*
* #param string $domain
*/
public function setDomain($domain) {
$this->domain = $domain;
return $this;
}
/**
* Returns root path of the website
*
* #return string
*/
private function getDomain() {
return $this->domain;
}
/**
* Returns XMLWriter object instance
*
* #return \XMLWriter
*/
private function getWriter() {
return $this->writer;
}
/**
* Assigns XMLWriter object instance
*
* #param \XMLWriter $writer
*/
private function setWriter(\XMLWriter $writer) {
$this->writer = $writer;
}
/**
* Returns path of sitemaps
*
* #return string
*/
private function getPath() {
return $this->path;
}
/**
* Sets paths of sitemaps
*
* #param string $path
* #return Sitemap
*/
public function setPath($path) {
$this->path = $path;
return $this;
}
/**
* Returns filename of sitemap file
*
* #return string
*/
private function getFilename() {
return $this->filename;
}
/**
* Sets filename of sitemap file
*
* #param string $filename
* #return Sitemap
*/
public function setFilename($filename) {
$this->filename = $filename;
return $this;
}
/**
* Returns current item count
*
* #return int
*/
private function getCurrentItem() {
return $this->current_item;
}
/**
* Increases item counter
*
*/
private function incCurrentItem() {
$this->current_item = $this->current_item + 1;
}
/**
* Returns current sitemap file count
*
* #return int
*/
private function getCurrentSitemap() {
return $this->current_sitemap;
}
/**
* Increases sitemap file count
*
*/
private function incCurrentSitemap() {
$this->current_sitemap = $this->current_sitemap + 1;
}
/**
* Prepares sitemap XML document
*
*/
private function startSitemap() {
$this->setWriter(new \XMLWriter());
if ($this->getCurrentSitemap()) {
$this->getWriter()->openURI($this->getPath() . $this->getFilename() . self::SEPERATOR . $this->getCurrentSitemap() . self::EXT);
} else {
$this->getWriter()->openURI($this->getPath() . $this->getFilename() . self::EXT);
}
$this->getWriter()->startDocument('1.0', 'UTF-8');
$this->getWriter()->setIndent(true);
$this->getWriter()->startElement('urlset');
$this->getWriter()->writeAttribute('xmlns', self::SCHEMA);
}
/**
* Adds an item to sitemap
*
* #param string $loc URL of the page. This value must be less than 2,048 characters.
* #param string|null $priority The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0.
* #param string|null $changefreq How frequently the page is likely to change. Valid values are always, hourly, daily, weekly, monthly, yearly and never.
* #param string|int|null $lastmod The date of last modification of url. Unix timestamp or any English textual datetime description.
* #return Sitemap
*/
public function addItem($loc, $priority = self::DEFAULT_PRIORITY, $changefreq = NULL, $lastmod = NULL) {
if (($this->getCurrentItem() % self::ITEM_PER_SITEMAP) == 0) {
if ($this->getWriter() instanceof \XMLWriter) {
$this->endSitemap();
}
$this->startSitemap();
$this->incCurrentSitemap();
}
$this->incCurrentItem();
$this->getWriter()->startElement('url');
$this->getWriter()->writeElement('loc', $this->getDomain() . $loc);
if($priority !== null)
$this->getWriter()->writeElement('priority', $priority);
if ($changefreq)
$this->getWriter()->writeElement('changefreq', $changefreq);
if ($lastmod)
$this->getWriter()->writeElement('lastmod', $this->getLastModifiedDate($lastmod));
$this->getWriter()->endElement();
return $this;
}
/**
* Prepares given date for sitemap
*
* #param string $date Unix timestamp or any English textual datetime description
* #return string Year-Month-Day formatted date.
*/
private function getLastModifiedDate($date) {
if (ctype_digit($date)) {
return date('Y-m-d', $date);
} else {
$date = strtotime($date);
return date('Y-m-d', $date);
}
}
/**
* Finalizes tags of sitemap XML document.
*
*/
private function endSitemap() {
if (!$this->getWriter()) {
$this->startSitemap();
}
$this->getWriter()->endElement();
$this->getWriter()->endDocument();
}
/**
* Writes Google sitemap index for generated sitemap files
*
* #param string $loc Accessible URL path of sitemaps
* #param string|int $lastmod The date of last modification of sitemap. Unix timestamp or any English textual datetime description.
*/
public function createSitemapIndex($loc, $lastmod = 'Today') {
$this->endSitemap();
$indexwriter = new \XMLWriter();
$indexwriter->openURI($this->getPath() . $this->getFilename() . self::SEPERATOR . self::INDEX_SUFFIX . self::EXT);
$indexwriter->startDocument('1.0', 'UTF-8');
$indexwriter->setIndent(true);
$indexwriter->startElement('sitemapindex');
$indexwriter->writeAttribute('xmlns', self::SCHEMA);
for ($index = 0; $index < $this->getCurrentSitemap(); $index++) {
$indexwriter->startElement('sitemap');
$indexwriter->writeElement('loc', $loc . $this->getFilename() . ($index ? self::SEPERATOR . $index : '') . self::EXT);
$indexwriter->writeElement('lastmod', $this->getLastModifiedDate($lastmod));
$indexwriter->endElement();
}
$indexwriter->endElement();
$indexwriter->endDocument();
}
}
I can add item using:
$sitemap->addItem('/', '1.0', 'daily', 'Today');
and add sitemapindex using: $sitemap->createSitemapIndex('http://example.com/sitemap/', 'Today'); Now I need to generate multiple sitemap and dynamic with MySQL database for each month archive:
$sql = "SELECT YEAR(FROM_UNIXTIME(timestamp)) AS YEAR,
MONTH(FROM_UNIXTIME(timestamp)) AS MONTH
FROM ".NEWS_ARTICLES." GROUP BY YEAR, MONTH ORDER BY YEAR DESC, MONTH ";
$newsdata = DataAccess::Fetch($sql);
$currentYear = null;
foreach($newsdata AS $news){
$sitemap->setFilename('posts-.'.$news['MONTH'].'-'.$news['YEAR'].'');
$sitemap->addItem('/post/' . $news['slug'], '0.6', 'weekly', $post['created_at']);
}
But in action I see one file and result data. How do can I generate one xml file for each month and put/insert data to this file (example:posts-6-2016.xml posts-7-2016.xml)?!
The Sitemap class only allows for one $filename which means you can create multiple instances of the class and set the file:
foreach($newsdata AS $news){
$sitemap = new Sitemap('http://example.com/');
$sitemap->setFilename('posts-.'.$news['MONTH'].'-'.$news['YEAR'].'');
$sitemap->addItem('/post/' . $news['slug'], '0.6', 'weekly', $post['created_at']);
}
Assuming that the additional code you're using is creating a sitemap file correctly, creating a new instance should create multiple files properly.
Related
I am trying to use this but keep getting an error message:
After editing the file on the web page the only thing showing up is "[".
Can anyone please advise me on how to resolve my issue.
I am a first year student I am not very experienced. This is my code:
<?php
include('forecast.io.php');
$apiKeyParam = $_GET["apiKey"];
$latParam = $_GET["lat"];
$lonParam = $_GET["lon"];
$unitsParam = $_GET["units"];
$langParam = (isset($_GET["lang"]) ? $_GET["lang"] : null);
$units = 'us'; // Can be set to 'us', 'si', 'ca', 'uk' or 'auto' (see forecast.io API); default is auto
$lang = 'en'; // Can be set to 'en', 'de', 'pl', 'es', 'fr', 'it', 'tet' or 'x-pig-latin' (see forecast.io API); default is 'en'
if($unitsParam != "") {
$units = $unitsParam;
}
if($langParam != "") {
$lang = $langParam;
}
//error_log(date(DATE_RFC822)." -- api=".$apiKeyParam.",lat=".$latParam.",lon=".$lonParam.",units=".$units.",lang=".$lang."\n", 3, '/home/weather.log');
$forecast = new ForecastIO($apiKeyParam, $units, $lang);
$condition = $forecast;
echo "CURRENT_TEMP=".round($condition->getTemperature())."\n";
echo "CURRENT_HUMIDITY=".($condition->getHumidity()*100)."\n";
echo "CURRENT_ICON=".($condition->getIcon())."\n";
echo "CURRENT_SUMMARY=".$condition->getSummary()."\n";
$conditions_week = $forecast->getForecastWeek($latParam, $lonParam);
echo "MAX_TEMP_TODAY=".round($conditions_week[0]->getMaxTemperature()) . "\n";
echo "MIN_TEMP_TODAY=".round($conditions_week[0]->getMinTemperature()) . "\n";
echo "ICON_TODAY=".$conditions_week[0]->getIcon()."\n";
echo "SUMMARY_TODAY=".$conditions_week[0]->getSummary()."\n";
echo "MAX_TEMP_TOMORROW=" . round($conditions_week[1]->getMaxTemperature()) . "\n";
echo "ICON_TOMORROW=".$conditions_week[1]->getIcon()."\n";
echo "MIN_TEMP_TOMORROW=".round($conditions_week[1]->getMinTemperature()) . "\n";
echo "SUMMARY_TODAY=".$conditions_week[1]->getSummary()."\n";
?>
This is my forecast.io.php:
<?php
/**
* Helper Class for forecast.io webservice
*/
class ForecastIO
{
private $api_key;
private $units;
private $language;
const API_ENDPOINT ='https://darksky.net/forecast/53.2789,-9.0109/uk12/en';
/**
* Create a new instance
*
* #param String $api_key
* #param String $units
* #param String $language
*/
function __construct($api_key, $units = 'auto', $language = 'en')
{
$this->api_key = $api_key;
$this->units = $units;
$this->language = $language;
}
/**
* #return string
*/
public function getUnits()
{
return $this->units;
}
/**
* #param string $units
*/
public function setUnits($units)
{
$this->units = $units;
}
/**
* #return string
*/
public function getLanguage()
{
return $this->language;
}
/**
* #param string $language
*/
public function setLanguage($language)
{
$this->language = $language;
}
private function requestData($latitude, $longitude, $timestamp = false, $exclusions = false)
{
$validUnits = array('auto', 'us', 'si', 'ca', 'uk');
if (in_array($this->units, $validUnits)) {
$request_url = self::API_ENDPOINT .
$this->api_key . '/' .
$latitude . ',' . $longitude .
($timestamp ? ',' . $timestamp : '') .
'?units=' . $this->units . '&lang=' . $this->language .
($exclusions ? '&exclude=' . $exclusions : '');
/**
* Use Buffer to cache API-requests if initialized
* (if not, just get the latest data)
*
* More info: http://git.io/FoO2Qw
*/
if (class_exists('Buffer')) {
$cache = new Buffer();
$content = $cache->data($request_url);
} else {
$content = file_get_contents($request_url);
}
} else {
return false;
}
if (!empty($content)) {
return json_decode($content);
} else {
return false;
}
}
/**
* Will return the current conditions
*
* #param float $latitude
* #param float $longitude
* #return \ForecastIOConditions|boolean
*/
public function getCurrentConditions($latitude, $longitude)
{
$data = $this->requestData($latitude, $longitude);
}
/**
* Will return historical conditions for day of given timestamp
*
* #param float $latitude
* #param float $longitude
* #param int $timestamp
* #return \ForecastIOConditions|boolean
*/
public function getHistoricalConditions($latitude, $longitude, $timestamp)
{
$exclusions = 'currently,minutely,hourly,alerts,flags';
$data = $this->requestData($latitude, $longitude, $timestamp, $exclusions);
if ($data !== false) {
return new ForecastIOConditions($data->daily->data[0]);
} else {
return null;
}
}
/**
* Will return conditions on hourly basis for today
*
* #param type $latitude
* #param type $longitude
* #return \ForecastIOConditions|boolean
*/
public function getForecastToday($latitude, $longitude)
{
$data = $this->requestData($latitude, $longitude);
if ($data !== false) {
$conditions = array();
$today = date('Y-m-d');
foreach ($data->hourly->data as $raw_data) {
if (date('Y-m-d', $raw_data->time) == $today) {
$conditions[] = new ForecastIOConditions($raw_data);
}
}
return $conditions;
} else {
return false;
}
}
/**
* Will return daily conditions for next seven days
*
* #param float $latitude
* #param float $longitude
* #return \ForecastIOConditions|boolean
*/
public function getForecastWeek($latitude, $longitude)
{
$data = $this->requestData($latitude, $longitude);
if ($data !== false) {
$conditions = array();
foreach ($data->daily->data as $raw_data) {
$conditions[] = new ForecastIOConditions($raw_data);
}
return $conditions;
} else {
return false;
}
}
}
/**
* Wrapper for get data by getters
*/
class ForecastIOConditions
{
private $raw_data;
function __construct($raw_data)
{
$this->raw_data = $raw_data;
}
/**
* Will return the temperature
*
* #return String
*/
function getTemperature()
{
return $this->raw_data->temperature;
}
/**
* get the min temperature
*
* only available for week forecast
*
* #return type
*/
function getMinTemperature()
{
return $this->raw_data->temperatureMin;
}
/**
* get max temperature
*
* only available for week forecast
*
* #return type
*/
function getMaxTemperature()
{
return $this->raw_data->temperatureMax;
}
/**
* get apparent temperature (heat index/wind chill)
*
* only available for current conditions
*
* #return type
*/
function getApparentTemperature()
{
return $this->raw_data->apparentTemperature;
}
/**
* Get the summary of the conditions
*
* #return String
*/
function getSummary()
{
return $this->raw_data->summary;
}
/**
* Get the icon of the conditions
*
* #return String
*/
function getIcon()
{
return $this->raw_data->icon;
}
/**
* Get the time, when $format not set timestamp else formatted time
*
* #param String $format
* #return String
*/
function getTime($format = null)
{
if (!isset($format)) {
return $this->raw_data->time;
} else {
return date($format, $this->raw_data->time);
}
}
/**
* Get the pressure
*
* #return String
*/
function getPressure()
{
return $this->raw_data->pressure;
}
/**
* Get the dew point
*
* Available in the current conditions
*
* #return String
*/
function getDewPoint()
{
return $this->raw_data->dewPoint;
}
/**
* get humidity
*
* #return String
*/
function getHumidity()
{
return $this->raw_data->humidity;
}
/**
* Get the wind speed
*
* #return String
*/
function getWindSpeed()
{
return $this->raw_data->windSpeed;
}
/**
* Get wind direction
*
* #return type
*/
function getWindBearing()
{
return $this->raw_data->windBearing;
}
/**
* get precipitation type
*
* #return type
*/
function getPrecipitationType()
{
return $this->raw_data->precipType;
}
/**
* get the probability 0..1 of precipitation type
*
* #return type
*/
function getPrecipitationProbability()
{
return $this->raw_data->precipProbability;
}
/**
* Get the cloud cover
*
* #return type
*/
function getCloudCover()
{
return $this->raw_data->cloudCover;
}
/**
* get sunrise time
*
* only available for week forecast
*
* #param String $format String to format date pph date
*
* #return type
*/
function getSunrise($format = null)
{
if (!isset($format)) {
return $this->raw_data->sunriseTime;
} else {
return date($format, $this->raw_data->sunriseTime);
}
}
/**
* get sunset time
*
* only available for week forecast
*
* #param String $format String to format date pph date
*
* #return type
*/
function getSunset($format = null)
{
if (!isset($format)) {
return $this->raw_data->sunsetTime;
} else {
return date($format, $this->raw_data->sunsetTime);
}
}
}
Where am I going wrong? It's line 19 causing the issue.
In your code method getCurrentConditions is a void method and doesn't return anything. Update the method content to a something similar as getHistoricalConditions where you instantiate ForecastIOConditions class and return it.
Do note that your code may still fail unless the method is guaranteed to return a value and you should wrap it in an if statement.
$condition = $forecast->getCurrentConditions($latParam, $lonParam);
if ($condition) {
echo "CURRENT_TEMP=".round($condition->getTemperature())."\n";
}
Line (18):
$condition = $forecast->getCurrentConditions($latParam, $lonParam);
ought to return an instance of class ForecastIOConditions as promised in the comment block above the definition. At the moment, it doesn't so the call to the member function getTemperature causes the error.
EDIT in the light of edited question:
These lines:
$forecast = new ForecastIO($apiKeyParam, $units, $lang);
$condition = $forecast->getCurrentConditions($latParam, $lonParam);
echo "CURRENT_TEMP=".round($condition->getTemperature())."\n";
are still wrong. $forecast does now contain an instance of ForecastIO, which is what $forecast->getCurrentConditions(...) should be returning. So, in order to take your code a stage further, change the second line above to:
$condition = $forecast
Once you've got something working, you fix getCurrentConditions(..) to make it return the instance of ForecastIO.
I recently moved one of my sites to a new dedicated server running the latest version of PHP. In my php-based Knowledgebase section of the site, I am getting the following error:
Strict Standards: Declaration of API_RATING::multiDelete() should be compatible with API::multiDelete($ids = 0) in /home/givebrad/public_html/kb/lib/api/class.rating.php on line 156
Line 156 is the last closing } at the bottom of the file. Below is the code for class-rating.php. Can anyone help me out to figure out how to fix this?
<?php
require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'class.api.php');
class API_RATING extends API
{
var $rateid = 0;
var $questionid = 0;
var $ip = '';
var $ratedat = '';
var $fields = array (
'rateid',
'questionid',
'ip',
'ratedat',
'ratingemail',
'ratingmessage'
);
var $pk = 'rateid';
/**
* create
* create a new rating in the database
*
* #return bool was the creation successful ?
*/
function create()
{
$_POST['ratedat'] = date('Y-m-d H:i:s');
$_POST['ip'] = $_SERVER['REMOTE_ADDR'];
return parent::create();
}
/**
* multiDelete
* Delete multiple rating ids. Update each associated question.
*
* #return bool was the delete successful?
*/
function multiDelete($ids) {
//Get the question ids
$objArray = $this->loadMultiByPK($ids);
foreach ($objArray as $rateObj) {
$questionObj = new API_QUESTION();
$questionObj->load($rateObj->questionid);
$questionObj->negvotes--;
$questionObj->score -= SCORE_MODIFIER;
$questionObj->updateField("negvotes", $questionObj->negvotes);
$questionObj->updateField("score", $questionObj->score);
}
//Delete from the main table
if (!parent::multiDelete($ids)) {
return false;
}
return true;
}
/**
* validate_rateid
*
* Ensure the rate id is a pos int
*
* #param string $var
*
* #return bool
*/
function validate_rateid($var)
{
return $this->is_positive_int($var);
}
/**
* validate_questionid
*
* Ensure the questionid is pos int
*
* #return bool
*/
function validate_questionid($var)
{
return $this->is_positive_int($var);
}
/**
* validate_ip
*
* Ensure the ip is an ipv4 address
*
* #param $var the ip to validate
*
* #return bool
*/
function validate_ip($var)
{
return $this->is_ip($var);
}
/**
* validate_ratedat
*
* Ensure the rated at date is in the standard date format
*
* #param string $var
*
* #return bool
*/
function validate_ratedat($var)
{
return $this->is_standard_date($var);
}
/**
* validate_email
*
* Ensure the email address for this rate entry is valid.
*
* #param string $var
*
* #return bool
*/
function validate_ratingemail(&$var)
{
if ((trim($var) == "") || (trim($var) == GetLang("WhyUnhelpfulEmail"))) {
$var = "";
return true;
} else {
return is_email_address($var);
}
}
/**
* validate_ratingmessage
*
* Ensure there is a message and its not blank.
*
* #param string $var
*
* #return bool
*/
function validate_ratingmessage(&$var)
{
if (strlen(trim($var)) > 250) {
$var = substr(trim($var),0,250);
return true;
} else {
return (trim($var) != "");
}
}
}
?>
This function :
function multiDelete($ids) {
Should be identic with it's parent function, find out the same function in class API, the nums, default value and type of the params should be same;
I asked this before, Strict Standards: Declaration of ' ' should be compatible with ' '
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
WAMP Stack PHP “Fatal error: Class ‘SoapClient’ not found”
I downloaded a library from this site library and when I tried to use it's examples it says : "Fatal error: Class 'SoapClient' not found in C:\wamp\www\Amazon-ECS\Exeu-Amazon-ECS-PHP-Library-9030053\lib\AmazonECS.class.php on line 231" How should I able to fix this?
<?php
/**
* Amazon ECS Class
* http://www.amazon.com
* =====================
*
* This class fetchs productinformation via the Product Advertising API by Amazon (formerly ECS).
* It supports three basic operations: ItemSearch, ItemLookup and BrowseNodeLookup.
* These operations could be expanded with extra prarmeters to specialize the query.
*
* Requirement is the PHP extension SOAP.
*
* #package AmazonECS
* #license http://www.gnu.org/licenses/gpl.txt GPL
* #version 1.3.4-DEV
* #author Exeu <exeu65#googlemail.com>
* #contributor Julien Chaumond <chaumond#gmail.com>
* #link http://github.com/Exeu/Amazon-ECS-PHP-Library/wiki Wiki
* #link http://github.com/Exeu/Amazon-ECS-PHP-Library Source
*/
class AmazonECS
{
const RETURN_TYPE_ARRAY = 1;
const RETURN_TYPE_OBJECT = 2;
/**
* Baseconfigurationstorage
*
* #var array
*/
private $requestConfig = array(
'requestDelay' => false
);
/**
* Responseconfigurationstorage
*
* #var array
*/
private $responseConfig = array(
'returnType' => self::RETURN_TYPE_OBJECT,
'responseGroup' => 'Small',
'optionalParameters' => array()
);
/**
* All possible locations
*
* #var array
*/
private $possibleLocations = array('de', 'com', 'co.uk', 'ca', 'fr', 'co.jp', 'it', 'cn', 'es');
/**
* The WSDL File
*
* #var string
*/
protected $webserviceWsdl = 'http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl';
/**
* The SOAP Endpoint
*
* #var string
*/
protected $webserviceEndpoint = 'https://webservices.amazon.%%COUNTRY%%/onca/soap?Service=AWSECommerceService';
/**
* #param string $accessKey
* #param string $secretKey
* #param string $country
* #param string $associateTag
*/
public function __construct($accessKey, $secretKey, $country, $associateTag)
{
if (empty($accessKey) || empty($secretKey))
{
throw new Exception('No Access Key or Secret Key has been set');
}
$this->requestConfig['accessKey'] = $accessKey;
$this->requestConfig['secretKey'] = $secretKey;
$this->associateTag($associateTag);
$this->country($country);
}
/**
* execute search
*
* #param string $pattern
*
* #return array|object return type depends on setting
*
* #see returnType()
*/
public function search($pattern, $nodeId = null)
{
if (false === isset($this->requestConfig['category']))
{
throw new Exception('No Category given: Please set it up before');
}
$browseNode = array();
if (null !== $nodeId && true === $this->validateNodeId($nodeId))
{
$browseNode = array('BrowseNode' => $nodeId);
}
$params = $this->buildRequestParams('ItemSearch', array_merge(
array(
'Keywords' => $pattern,
'SearchIndex' => $this->requestConfig['category']
),
$browseNode
));
return $this->returnData(
$this->performSoapRequest("ItemSearch", $params)
);
}
/**
* execute ItemLookup request
*
* #param string $asin
*
* #return array|object return type depends on setting
*
* #see returnType()
*/
public function lookup($asin)
{
$params = $this->buildRequestParams('ItemLookup', array(
'ItemId' => $asin,
));
return $this->returnData(
$this->performSoapRequest("ItemLookup", $params)
);
}
/**
* Implementation of BrowseNodeLookup
* This allows to fetch information about nodes (children anchestors, etc.)
*
* #param integer $nodeId
*/
public function browseNodeLookup($nodeId)
{
$this->validateNodeId($nodeId);
$params = $this->buildRequestParams('BrowseNodeLookup', array(
'BrowseNodeId' => $nodeId
));
return $this->returnData(
$this->performSoapRequest("BrowseNodeLookup", $params)
);
}
/**
* Implementation of SimilarityLookup
* This allows to fetch information about product related to the parameter product
*
* #param string $asin
*/
public function similarityLookup($asin)
{
$params = $this->buildRequestParams('SimilarityLookup', array(
'ItemId' => $asin
));
return $this->returnData(
$this->performSoapRequest("SimilarityLookup", $params)
);
}
/**
* Builds the request parameters
*
* #param string $function
* #param array $params
*
* #return array
*/
protected function buildRequestParams($function, array $params)
{
$associateTag = array();
if(false === empty($this->requestConfig['associateTag']))
{
$associateTag = array('AssociateTag' => $this->requestConfig['associateTag']);
}
return array_merge(
$associateTag,
array(
'AWSAccessKeyId' => $this->requestConfig['accessKey'],
'Request' => array_merge(
array('Operation' => $function),
$params,
$this->responseConfig['optionalParameters'],
array('ResponseGroup' => $this->prepareResponseGroup())
)));
}
/**
* Prepares the responsegroups and returns them as array
*
* #return array|prepared responsegroups
*/
protected function prepareResponseGroup()
{
if (false === strstr($this->responseConfig['responseGroup'], ','))
return $this->responseConfig['responseGroup'];
return explode(',', $this->responseConfig['responseGroup']);
}
/**
* #param string $function Name of the function which should be called
* #param array $params Requestparameters 'ParameterName' => 'ParameterValue'
*
* #return array The response as an array with stdClass objects
*/
protected function performSoapRequest($function, $params)
{
if (true === $this->requestConfig['requestDelay']) {
sleep(1);
}
$soapClient = new SoapClient(
$this->webserviceWsdl,
array('exceptions' => 1)
);
$soapClient->__setLocation(str_replace(
'%%COUNTRY%%',
$this->responseConfig['country'],
$this->webserviceEndpoint
));
$soapClient->__setSoapHeaders($this->buildSoapHeader($function));
return $soapClient->__soapCall($function, array($params));
}
/**
* Provides some necessary soap headers
*
* #param string $function
*
* #return array Each element is a concrete SoapHeader object
*/
protected function buildSoapHeader($function)
{
$timeStamp = $this->getTimestamp();
$signature = $this->buildSignature($function . $timeStamp);
return array(
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'AWSAccessKeyId',
$this->requestConfig['accessKey']
),
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'Timestamp',
$timeStamp
),
new SoapHeader(
'http://security.amazonaws.com/doc/2007-01-01/',
'Signature',
$signature
)
);
}
/**
* provides current gm date
*
* primary needed for the signature
*
* #return string
*/
final protected function getTimestamp()
{
return gmdate("Y-m-d\TH:i:s\Z");
}
/**
* provides the signature
*
* #return string
*/
final protected function buildSignature($request)
{
return base64_encode(hash_hmac("sha256", $request, $this->requestConfig['secretKey'], true));
}
/**
* Basic validation of the nodeId
*
* #param integer $nodeId
*
* #return boolean
*/
final protected function validateNodeId($nodeId)
{
if (false === is_numeric($nodeId) || $nodeId <= 0)
{
throw new InvalidArgumentException(sprintf('Node has to be a positive Integer.'));
}
return true;
}
/**
* Returns the response either as Array or Array/Object
*
* #param object $object
*
* #return mixed
*/
protected function returnData($object)
{
switch ($this->responseConfig['returnType'])
{
case self::RETURN_TYPE_OBJECT:
return $object;
break;
case self::RETURN_TYPE_ARRAY:
return $this->objectToArray($object);
break;
default:
throw new InvalidArgumentException(sprintf(
"Unknwon return type %s", $this->responseConfig['returnType']
));
break;
}
}
/**
* Transforms the responseobject to an array
*
* #param object $object
*
* #return array An arrayrepresentation of the given object
*/
protected function objectToArray($object)
{
$out = array();
foreach ($object as $key => $value)
{
switch (true)
{
case is_object($value):
$out[$key] = $this->objectToArray($value);
break;
case is_array($value):
$out[$key] = $this->objectToArray($value);
break;
default:
$out[$key] = $value;
break;
}
}
return $out;
}
/**
* set or get optional parameters
*
* if the argument params is null it will reutrn the current parameters,
* otherwise it will set the params and return itself.
*
* #param array $params the optional parameters
*
* #return array|AmazonECS depends on params argument
*/
public function optionalParameters($params = null)
{
if (null === $params)
{
return $this->responseConfig['optionalParameters'];
}
if (false === is_array($params))
{
throw new InvalidArgumentException(sprintf(
"%s is no valid parameter: Use an array with Key => Value Pairs", $params
));
}
$this->responseConfig['optionalParameters'] = $params;
return $this;
}
/**
* Set or get the country
*
* if the country argument is null it will return the current
* country, otherwise it will set the country and return itself.
*
* #param string|null $country
*
* #return string|AmazonECS depends on country argument
*/
public function country($country = null)
{
if (null === $country)
{
return $this->responseConfig['country'];
}
if (false === in_array(strtolower($country), $this->possibleLocations))
{
throw new InvalidArgumentException(sprintf(
"Invalid Country-Code: %s! Possible Country-Codes: %s",
$country,
implode(', ', $this->possibleLocations)
));
}
$this->responseConfig['country'] = strtolower($country);
return $this;
}
/**
* Setting/Getting the amazon category
*
* #param string $category
*
* #return string|AmazonECS depends on category argument
*/
public function category($category = null)
{
if (null === $category)
{
return isset($this->requestConfig['category']) ? $this->requestConfig['category'] : null;
}
$this->requestConfig['category'] = $category;
return $this;
}
/**
* Setting/Getting the responsegroup
*
* #param string $responseGroup Comma separated groups
*
* #return string|AmazonECS depends on responseGroup argument
*/
public function responseGroup($responseGroup = null)
{
if (null === $responseGroup)
{
return $this->responseConfig['responseGroup'];
}
$this->responseConfig['responseGroup'] = $responseGroup;
return $this;
}
/**
* Setting/Getting the returntype
* It can be an object or an array
*
* #param integer $type Use the constants RETURN_TYPE_ARRAY or RETURN_TYPE_OBJECT
*
* #return integer|AmazonECS depends on type argument
*/
public function returnType($type = null)
{
if (null === $type)
{
return $this->responseConfig['returnType'];
}
$this->responseConfig['returnType'] = $type;
return $this;
}
/**
* Setter/Getter of the AssociateTag.
* This could be used for late bindings of this attribute
*
* #param string $associateTag
*
* #return string|AmazonECS depends on associateTag argument
*/
public function associateTag($associateTag = null)
{
if (null === $associateTag)
{
return $this->requestConfig['associateTag'];
}
$this->requestConfig['associateTag'] = $associateTag;
return $this;
}
/**
* #deprecated use returnType() instead
*/
public function setReturnType($type)
{
return $this->returnType($type);
}
/**
* Setting the resultpage to a specified value.
* Allows to browse resultsets which have more than one page.
*
* #param integer $page
*
* #return AmazonECS
*/
public function page($page)
{
if (false === is_numeric($page) || $page <= 0)
{
throw new InvalidArgumentException(sprintf(
'%s is an invalid page value. It has to be numeric and positive',
$page
));
}
$this->responseConfig['optionalParameters'] = array_merge(
$this->responseConfig['optionalParameters'],
array("ItemPage" => $page)
);
return $this;
}
/**
* Enables or disables the request delay.
* If it is enabled (true) every request is delayed one second to get rid of the api request limit.
*
* Reasons for this you can read on this site:
* https://affiliate-program.amazon.com/gp/advertising/api/detail/faq.html
*
* By default the requestdelay is disabled
*
* #param boolean $enable true = enabled, false = disabled
*
* #return boolean|AmazonECS depends on enable argument
*/
public function requestDelay($enable = null)
{
if (false === is_null($enable) && true === is_bool($enable))
{
$this->requestConfig['requestDelay'] = $enable;
return $this;
}
return $this->requestConfig['requestDelay'];
}
}
The error appears to be caused by the version of PHP that you have does not have the SOAP extension enabled.
To resolve this simply start wamp, click on the wamp system tray icon. Within this screen select PHP then PHP extensions. This will display a list of extensions. Ensure that php_soap is ticked.
If you intend to access soap servers that use HTTPs then you will also ensure php_openssl is ticked.
I'm trying to use PHPExcel with Codeigniter, but I'm running into issues. I extracted the class files from the PHPExcel download and placed them in the 'application/libraries' folder for Codeigniter.
However when I try to load the necessary libraries:
$this->load->library('PHPExcel');
$this->load->library('PHPExcel/IOFactory');
I get the error "Non-existent class: IOFactory".
I've checked that iofactory file is in the PHPExcel file, and it is there. Am I supposed to have the classes located somewhere else? What else am I doing wrong?
Try something like this:
$this->load->library('PHPExcel');
$xl_obj = new PHPExcel();
$reader = PHPExcel_IOFactory::createReader('Excel5');
$reader->setReadDataOnly(true);
$file = $reader->load('/PATH/FILENAME.EXT');
It works!
My method for this was to put the PHPExcel folder in /application/libraries folder, then create a wrapper file in the libraries folder;
PHPExcel.php
<?php
/**
* PHPExcel
*
* Copyright (c) 2006 - 2011 PHPExcel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* #category PHPExcel
* #package PHPExcel
* #copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
* #license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
* #version 1.7.6, 2011-02-27
*/
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
/**
* PHPExcel
*
* #category PHPExcel
* #package PHPExcel
* #copyright Copyright (c) 2006 - 2011 PHPExcel (http://www.codeplex.com/PHPExcel)
*/
class PHPExcel
{
/**
* Document properties
*
* #var PHPExcel_DocumentProperties
*/
private $_properties;
/**
* Document security
*
* #var PHPExcel_DocumentSecurity
*/
private $_security;
/**
* Collection of Worksheet objects
*
* #var PHPExcel_Worksheet[]
*/
private $_workSheetCollection = array();
/**
* Active sheet index
*
* #var int
*/
private $_activeSheetIndex = 0;
/**
* Named ranges
*
* #var PHPExcel_NamedRange[]
*/
private $_namedRanges = array();
/**
* CellXf supervisor
*
* #var PHPExcel_Style
*/
private $_cellXfSupervisor;
/**
* CellXf collection
*
* #var PHPExcel_Style[]
*/
private $_cellXfCollection = array();
/**
* CellStyleXf collection
*
* #var PHPExcel_Style[]
*/
private $_cellStyleXfCollection = array();
/**
* Create a new PHPExcel with one Worksheet
*/
public function __construct()
{
// Initialise worksheet collection and add one worksheet
$this->_workSheetCollection = array();
$this->_workSheetCollection[] = new PHPExcel_Worksheet($this);
$this->_activeSheetIndex = 0;
// Create document properties
$this->_properties = new PHPExcel_DocumentProperties();
// Create document security
$this->_security = new PHPExcel_DocumentSecurity();
// Set named ranges
$this->_namedRanges = array();
// Create the cellXf supervisor
$this->_cellXfSupervisor = new PHPExcel_Style(true);
$this->_cellXfSupervisor->bindParent($this);
// Create the default style
$this->addCellXf(new PHPExcel_Style);
$this->addCellStyleXf(new PHPExcel_Style);
}
public function disconnectWorksheets() {
foreach($this->_workSheetCollection as $k => &$worksheet) {
$worksheet->disconnectCells();
$this->_workSheetCollection[$k] = null;
}
unset($worksheet);
$this->_workSheetCollection = array();
}
/**
* Get properties
*
* #return PHPExcel_DocumentProperties
*/
public function getProperties()
{
return $this->_properties;
}
/**
* Set properties
*
* #param PHPExcel_DocumentProperties $pValue
*/
public function setProperties(PHPExcel_DocumentProperties $pValue)
{
$this->_properties = $pValue;
}
/**
* Get security
*
* #return PHPExcel_DocumentSecurity
*/
public function getSecurity()
{
return $this->_security;
}
/**
* Set security
*
* #param PHPExcel_DocumentSecurity $pValue
*/
public function setSecurity(PHPExcel_DocumentSecurity $pValue)
{
$this->_security = $pValue;
}
/**
* Get active sheet
*
* #return PHPExcel_Worksheet
*/
public function getActiveSheet()
{
return $this->_workSheetCollection[$this->_activeSheetIndex];
}
/**
* Create sheet and add it to this workbook
*
* #return PHPExcel_Worksheet
*/
public function createSheet($iSheetIndex = null)
{
$newSheet = new PHPExcel_Worksheet($this);
$this->addSheet($newSheet, $iSheetIndex);
return $newSheet;
}
/**
* Add sheet
*
* #param PHPExcel_Worksheet $pSheet
* #param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
* #return PHPExcel_Worksheet
* #throws Exception
*/
public function addSheet(PHPExcel_Worksheet $pSheet = null, $iSheetIndex = null)
{
if(is_null($iSheetIndex))
{
$this->_workSheetCollection[] = $pSheet;
}
else
{
// Insert the sheet at the requested index
array_splice(
$this->_workSheetCollection,
$iSheetIndex,
0,
array($pSheet)
);
// Adjust active sheet index if necessary
if ($this->_activeSheetIndex >= $iSheetIndex) {
++$this->_activeSheetIndex;
}
}
return $pSheet;
}
/**
* Remove sheet by index
*
* #param int $pIndex Active sheet index
* #throws Exception
*/
public function removeSheetByIndex($pIndex = 0)
{
if ($pIndex > count($this->_workSheetCollection) - 1) {
throw new Exception("Sheet index is out of bounds.");
} else {
array_splice($this->_workSheetCollection, $pIndex, 1);
}
}
/**
* Get sheet by index
*
* #param int $pIndex Sheet index
* #return PHPExcel_Worksheet
* #throws Exception
*/
public function getSheet($pIndex = 0)
{
if ($pIndex > count($this->_workSheetCollection) - 1) {
throw new Exception("Sheet index is out of bounds.");
} else {
return $this->_workSheetCollection[$pIndex];
}
}
/**
* Get all sheets
*
* #return PHPExcel_Worksheet[]
*/
public function getAllSheets()
{
return $this->_workSheetCollection;
}
/**
* Get sheet by name
*
* #param string $pName Sheet name
* #return PHPExcel_Worksheet
* #throws Exception
*/
public function getSheetByName($pName = '')
{
$worksheetCount = count($this->_workSheetCollection);
for ($i = 0; $i < $worksheetCount; ++$i) {
if ($this->_workSheetCollection[$i]->getTitle() == $pName) {
return $this->_workSheetCollection[$i];
}
}
return null;
}
/**
* Get index for sheet
*
* #param PHPExcel_Worksheet $pSheet
* #return Sheet index
* #throws Exception
*/
public function getIndex(PHPExcel_Worksheet $pSheet)
{
foreach ($this->_workSheetCollection as $key => $value) {
if ($value->getHashCode() == $pSheet->getHashCode()) {
return $key;
}
}
}
/**
* Set index for sheet by sheet name.
*
* #param string $sheetName Sheet name to modify index for
* #param int $newIndex New index for the sheet
* #return New sheet index
* #throws Exception
*/
public function setIndexByName($sheetName, $newIndex)
{
$oldIndex = $this->getIndex($this->getSheetByName($sheetName));
$pSheet = array_splice(
$this->_workSheetCollection,
$oldIndex,
1
);
array_splice(
$this->_workSheetCollection,
$newIndex,
0,
$pSheet
);
return $newIndex;
}
/**
* Get sheet count
*
* #return int
*/
public function getSheetCount()
{
return count($this->_workSheetCollection);
}
/**
* Get active sheet index
*
* #return int Active sheet index
*/
public function getActiveSheetIndex()
{
return $this->_activeSheetIndex;
}
/**
* Set active sheet index
*
* #param int $pIndex Active sheet index
* #throws Exception
* #return PHPExcel_Worksheet
*/
public function setActiveSheetIndex($pIndex = 0)
{
if ($pIndex > count($this->_workSheetCollection) - 1) {
throw new Exception("Active sheet index is out of bounds.");
} else {
$this->_activeSheetIndex = $pIndex;
}
return $this->getActiveSheet();
}
/**
* Set active sheet index by name
*
* #param string $pValue Sheet title
* #return PHPExcel_Worksheet
* #throws Exception
*/
public function setActiveSheetIndexByName($pValue = '')
{
if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) {
$this->setActiveSheetIndex($worksheet->getParent()->getIndex($worksheet));
return $worksheet;
}
throw new Exception('Workbook does not contain sheet:' . $pValue);
}
/**
* Get sheet names
*
* #return string[]
*/
public function getSheetNames()
{
$returnValue = array();
$worksheetCount = $this->getSheetCount();
for ($i = 0; $i < $worksheetCount; ++$i) {
array_push($returnValue, $this->getSheet($i)->getTitle());
}
return $returnValue;
}
/**
* Add external sheet
*
* #param PHPExcel_Worksheet $pSheet External sheet to add
* #param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last)
* #throws Exception
* #return PHPExcel_Worksheet
*/
public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) {
if (!is_null($this->getSheetByName($pSheet->getTitle()))) {
throw new Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first.");
}
// count how many cellXfs there are in this workbook currently, we will need this below
$countCellXfs = count($this->_cellXfCollection);
// copy all the shared cellXfs from the external workbook and append them to the current
foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) {
$this->addCellXf(clone $cellXf);
}
// move sheet to this workbook
$pSheet->rebindParent($this);
// update the cellXfs
foreach ($pSheet->getCellCollection(false) as $cellID) {
$cell = $pSheet->getCell($cellID);
$cell->setXfIndex( $cell->getXfIndex() + $countCellXfs );
}
return $this->addSheet($pSheet, $iSheetIndex);
}
/**
* Get named ranges
*
* #return PHPExcel_NamedRange[]
*/
public function getNamedRanges() {
return $this->_namedRanges;
}
/**
* Add named range
*
* #param PHPExcel_NamedRange $namedRange
* #return PHPExcel
*/
public function addNamedRange(PHPExcel_NamedRange $namedRange) {
if ($namedRange->getScope() == null) {
// global scope
$this->_namedRanges[$namedRange->getName()] = $namedRange;
} else {
// local scope
$this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange;
}
return true;
}
/**
* Get named range
*
* #param string $namedRange
* #param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope
* #return PHPExcel_NamedRange|null
*/
public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
$returnValue = null;
if ($namedRange != '' && !is_null($namedRange)) {
// first look for global defined name
if (isset($this->_namedRanges[$namedRange])) {
$returnValue = $this->_namedRanges[$namedRange];
}
// then look for local defined name (has priority over global defined name if both names exist)
if (!is_null($pSheet) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
$returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange];
}
}
return $returnValue;
}
/**
* Remove named range
*
* #param string $namedRange
* #param PHPExcel_Worksheet|null $pSheet. Scope. Use null for global scope.
* #return PHPExcel
*/
public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) {
if (is_null($pSheet)) {
if (isset($this->_namedRanges[$namedRange])) {
unset($this->_namedRanges[$namedRange]);
}
} else {
if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) {
unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]);
}
}
return $this;
}
/**
* Get worksheet iterator
*
* #return PHPExcel_WorksheetIterator
*/
public function getWorksheetIterator() {
return new PHPExcel_WorksheetIterator($this);
}
/**
* Copy workbook (!= clone!)
*
* #return PHPExcel
*/
public function copy() {
$copied = clone $this;
$worksheetCount = count($this->_workSheetCollection);
for ($i = 0; $i < $worksheetCount; ++$i) {
$this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy();
$this->_workSheetCollection[$i]->rebindParent($this);
}
return $copied;
}
/**
* Implement PHP __clone to create a deep clone, not just a shallow copy.
*/
public function __clone() {
foreach($this as $key => $val) {
if (is_object($val) || (is_array($val))) {
$this->{$key} = unserialize(serialize($val));
}
}
}
/**
* Get the workbook collection of cellXfs
*
* #return PHPExcel_Style[]
*/
public function getCellXfCollection()
{
return $this->_cellXfCollection;
}
/**
* Get cellXf by index
*
* #param int $index
* #return PHPExcel_Style
*/
public function getCellXfByIndex($pIndex = 0)
{
return $this->_cellXfCollection[$pIndex];
}
/**
* Get cellXf by hash code
*
* #param string $pValue
* #return PHPExcel_Style|false
*/
public function getCellXfByHashCode($pValue = '')
{
foreach ($this->_cellXfCollection as $cellXf) {
if ($cellXf->getHashCode() == $pValue) {
return $cellXf;
}
}
return false;
}
/**
* Get default style
*
* #return PHPExcel_Style
* #throws Exception
*/
public function getDefaultStyle()
{
if (isset($this->_cellXfCollection[0])) {
return $this->_cellXfCollection[0];
}
throw new Exception('No default style found for this workbook');
}
/**
* Add a cellXf to the workbook
*
* #param PHPExcel_Style
*/
public function addCellXf(PHPExcel_Style $style)
{
$this->_cellXfCollection[] = $style;
$style->setIndex(count($this->_cellXfCollection) - 1);
}
/**
* Remove cellXf by index. It is ensured that all cells get their xf index updated.
*
* #param int $pIndex Index to cellXf
* #throws Exception
*/
public function removeCellXfByIndex($pIndex = 0)
{
if ($pIndex > count($this->_cellXfCollection) - 1) {
throw new Exception("CellXf index is out of bounds.");
} else {
// first remove the cellXf
array_splice($this->_cellXfCollection, $pIndex, 1);
// then update cellXf indexes for cells
foreach ($this->_workSheetCollection as $worksheet) {
foreach ($worksheet->getCellCollection(false) as $cellID) {
$cell = $worksheet->getCell($cellID);
$xfIndex = $cell->getXfIndex();
if ($xfIndex > $pIndex ) {
// decrease xf index by 1
$cell->setXfIndex($xfIndex - 1);
} else if ($xfIndex == $pIndex) {
// set to default xf index 0
$cell->setXfIndex(0);
}
}
}
}
}
/**
* Get the cellXf supervisor
*
* #return PHPExcel_Style
*/
public function getCellXfSupervisor()
{
return $this->_cellXfSupervisor;
}
/**
* Get the workbook collection of cellStyleXfs
*
* #return PHPExcel_Style[]
*/
public function getCellStyleXfCollection()
{
return $this->_cellStyleXfCollection;
}
/**
* Get cellStyleXf by index
*
* #param int $pIndex
* #return PHPExcel_Style
*/
public function getCellStyleXfByIndex($pIndex = 0)
{
return $this->_cellStyleXfCollection[$pIndex];
}
/**
* Get cellStyleXf by hash code
*
* #param string $pValue
* #return PHPExcel_Style|false
*/
public function getCellStyleXfByHashCode($pValue = '')
{
foreach ($this->_cellXfStyleCollection as $cellStyleXf) {
if ($cellStyleXf->getHashCode() == $pValue) {
return $cellStyleXf;
}
}
return false;
}
/**
* Add a cellStyleXf to the workbook
*
* #param PHPExcel_Style $pStyle
*/
public function addCellStyleXf(PHPExcel_Style $pStyle)
{
$this->_cellStyleXfCollection[] = $pStyle;
$pStyle->setIndex(count($this->_cellStyleXfCollection) - 1);
}
/**
* Remove cellStyleXf by index
*
* #param int $pIndex
* #throws Exception
*/
public function removeCellStyleXfByIndex($pIndex = 0)
{
if ($pIndex > count($this->_cellStyleXfCollection) - 1) {
throw new Exception("CellStyleXf index is out of bounds.");
} else {
array_splice($this->_cellStyleXfCollection, $pIndex, 1);
}
}
/**
* Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells
* and columns in the workbook
*/
public function garbageCollect()
{
// how many references are there to each cellXf ?
$countReferencesCellXf = array();
foreach ($this->_cellXfCollection as $index => $cellXf) {
$countReferencesCellXf[$index] = 0;
}
foreach ($this->getWorksheetIterator() as $sheet) {
// from cells
foreach ($sheet->getCellCollection(false) as $cellID) {
$cell = $sheet->getCell($cellID);
++$countReferencesCellXf[$cell->getXfIndex()];
}
// from row dimensions
foreach ($sheet->getRowDimensions() as $rowDimension) {
if ($rowDimension->getXfIndex() !== null) {
++$countReferencesCellXf[$rowDimension->getXfIndex()];
}
}
// from column dimensions
foreach ($sheet->getColumnDimensions() as $columnDimension) {
++$countReferencesCellXf[$columnDimension->getXfIndex()];
}
}
// remove cellXfs without references and create mapping so we can update xfIndex
// for all cells and columns
$countNeededCellXfs = 0;
foreach ($this->_cellXfCollection as $index => $cellXf) {
if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf
++$countNeededCellXfs;
} else {
unset($this->_cellXfCollection[$index]);
}
$map[$index] = $countNeededCellXfs - 1;
}
$this->_cellXfCollection = array_values($this->_cellXfCollection);
// update the index for all cellXfs
foreach ($this->_cellXfCollection as $i => $cellXf) {
$cellXf->setIndex($i);
}
// make sure there is always at least one cellXf (there should be)
if (count($this->_cellXfCollection) == 0) {
$this->_cellXfCollection[] = new PHPExcel_Style();
}
// update the xfIndex for all cells, row dimensions, column dimensions
foreach ($this->getWorksheetIterator() as $sheet) {
// for all cells
foreach ($sheet->getCellCollection(false) as $cellID) {
$cell = $sheet->getCell($cellID);
$cell->setXfIndex( $map[$cell->getXfIndex()] );
}
// for all row dimensions
foreach ($sheet->getRowDimensions() as $rowDimension) {
if ($rowDimension->getXfIndex() !== null) {
$rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] );
}
}
// for all column dimensions
foreach ($sheet->getColumnDimensions() as $columnDimension) {
$columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] );
}
}
// also do garbage collection for all the sheets
foreach ($this->getWorksheetIterator() as $sheet) {
$sheet->garbageCollect();
}
}
}
Then in my contoller;
$this->load->library('PHPExcel');
// Create new PHPExcel object
$excel_obj = new PHPExcel();
// Set properties
$excel_obj->getProperties()->setCreator($params['author'])
->setLastModifiedBy($params['author'])
->setTitle($params['title'])
->setSubject($params['subject'])
->setDescription($params['description']);
I really need to be able to extract the metadata from a .ttf true type font file.
I'm building a central database of all the fonts all our designers use (they're forever swapping fonts via email to take over design elements, etc). I want to get all the fonts, some have silly names like 00001.ttf, so file name is no help, but I know the fonts have metadata, I need some way to extract that in PHP.
Then I can create a loop to look through the directories I've specified, get this data (and any other data I can get at the same time, and add it to a database.
I just really need help with the reading of this metadata part.
I came across this link. It will do what you want (I've tested it and posted results). Just pass the class the path of the TTF file you want to parse the data out of. then use $fontinfo[1].' '.$fontinfo[2] for the name.
In case you don't want to register, here is the class
Resulting Data
Array
(
[1] => Almonte Snow
[2] => Regular
[3] => RayLarabie: Almonte Snow: 2000
[4] => Almonte Snow
[5] => Version 2.000 2004
[6] => AlmonteSnow
[8] => Ray Larabie
[9] => Ray Larabie
[10] => Larabie Fonts is able to offer unique free fonts through the generous support of visitors to the site. Making fonts is my full-time job and every donation, in any amount, enables me to continue running the site and creating new fonts. If you would like to support Larabie Fonts visit www.larabiefonts.com for details.
[11] => http://www.larabiefonts.com
[12] => http://www.typodermic.com
)
Usage
<?php
include 'ttfInfo.class.php';
$fontinfo = getFontInfo('c:\windows\fonts\_LDS_almosnow.ttf');
echo '<pre>';
print_r($fontinfo);
echo '</pre>';
?>
ttfInfo.class.php
<?php
/**
* ttfInfo class
* Retrieve data stored in a TTF files 'name' table
*
* #original author Unknown
* found at http://www.phpclasses.org/browse/package/2144.html
*
* #ported for used on http://www.nufont.com
* #author Jason Arencibia
* #version 0.2
* #copyright (c) 2006 GrayTap Media
* #website http://www.graytap.com
* #license GPL 2.0
* #access public
*
* #todo: Make it Retrieve additional information from other tables
*
*/
class ttfInfo {
/**
* variable $_dirRestriction
* Restrict the resource pointer to this directory and above.
* Change to 1 for to allow the class to look outside of it current directory
* #protected
* #var int
*/
protected $_dirRestriction = 1;
/**
* variable $_dirRestriction
* Restrict the resource pointer to this directory and above.
* Change to 1 for nested directories
* #protected
* #var int
*/
protected $_recursive = 0;
/**
* variable $fontsdir
* This is to declare this variable as protected
* don't edit this!!!
* #protected
*/
protected $fontsdir;
/**
* variable $filename
* This is to declare this varable as protected
* don't edit this!!!
* #protected
*/
protected $filename;
/**
* function setFontFile()
* set the filename
* #public
* #param string $data the new value
* #return object reference to this
*/
public function setFontFile($data)
{
if ($this->_dirRestriction && preg_match('[\.\/|\.\.\/]', $data))
{
$this->exitClass('Error: Directory restriction is enforced!');
}
$this->filename = $data;
return $this;
} // public function setFontFile
/**
* function setFontsDir()
* set the Font Directory
* #public
* #param string $data the new value
* #return object referrence to this
*/
public function setFontsDir($data)
{
if ($this->_dirRestriction && preg_match('[\.\/|\.\.\/]', $data))
{
$this->exitClass('Error: Directory restriction is enforced!');
}
$this->fontsdir = $data;
return $this;
} // public function setFontsDir
/**
* function readFontsDir()
* #public
* #return information contained in the TTF 'name' table of all fonts in a directory.
*/
public function readFontsDir()
{
if (empty($this->fontsdir)) { $this->exitClass('Error: Fonts Directory has not been set with setFontsDir().'); }
if (empty($this->backupDir)){ $this->backupDir = $this->fontsdir; }
$this->array = array();
$d = dir($this->fontsdir);
while (false !== ($e = $d->read()))
{
if($e != '.' && $e != '..')
{
$e = $this->fontsdir . $e;
if($this->_recursive && is_dir($e))
{
$this->setFontsDir($e);
$this->array = array_merge($this->array, readFontsDir());
}
else if ($this->is_ttf($e) === true)
{
$this->setFontFile($e);
$this->array[$e] = $this->getFontInfo();
}
}
}
if (!empty($this->backupDir)){ $this->fontsdir = $this->backupDir; }
$d->close();
return $this;
} // public function readFontsDir
/**
* function setProtectedVar()
* #public
* #param string $var the new variable
* #param string $data the new value
* #return object reference to this
* DISABLED, NO REAL USE YET
public function setProtectedVar($var, $data)
{
if ($var == 'filename')
{
$this->setFontFile($data);
} else {
//if (isset($var) && !empty($data))
$this->$var = $data;
}
return $this;
}
*/
/**
* function getFontInfo()
* #public
* #return information contained in the TTF 'name' table.
*/
public function getFontInfo()
{
$fd = fopen ($this->filename, "r");
$this->text = fread ($fd, filesize($this->filename));
fclose ($fd);
$number_of_tables = hexdec($this->dec2ord($this->text[4]).$this->dec2ord($this->text[5]));
for ($i=0;$i<$number_of_tables;$i++)
{
$tag = $this->text[12+$i*16].$this->text[12+$i*16+1].$this->text[12+$i*16+2].$this->text[12+$i*16+3];
if ($tag == 'name')
{
$this->ntOffset = hexdec(
$this->dec2ord($this->text[12+$i*16+8]).$this->dec2ord($this->text[12+$i*16+8+1]).
$this->dec2ord($this->text[12+$i*16+8+2]).$this->dec2ord($this->text[12+$i*16+8+3]));
$offset_storage_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+4]).$this->dec2ord($this->text[$this->ntOffset+5]));
$number_name_records_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+2]).$this->dec2ord($this->text[$this->ntOffset+3]));
}
}
$storage_dec = $offset_storage_dec + $this->ntOffset;
$storage_hex = strtoupper(dechex($storage_dec));
for ($j=0;$j<$number_name_records_dec;$j++)
{
$platform_id_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+0]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+1]));
$name_id_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+6]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+7]));
$string_length_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+8]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+9]));
$string_offset_dec = hexdec($this->dec2ord($this->text[$this->ntOffset+6+$j*12+10]).$this->dec2ord($this->text[$this->ntOffset+6+$j*12+11]));
if (!empty($name_id_dec) and empty($font_tags[$name_id_dec]))
{
for($l=0;$l<$string_length_dec;$l++)
{
if (ord($this->text[$storage_dec+$string_offset_dec+$l]) == '0') { continue; }
else { $font_tags[$name_id_dec] .= ($this->text[$storage_dec+$string_offset_dec+$l]); }
}
}
}
return $font_tags;
} // public function getFontInfo
/**
* function getCopyright()
* #public
* #return 'Copyright notice' contained in the TTF 'name' table at index 0
*/
public function getCopyright()
{
$this->info = $this->getFontInfo();
return $this->info[0];
} // public function getCopyright
/**
* function getFontFamily()
* #public
* #return 'Font Family name' contained in the TTF 'name' table at index 1
*/
public function getFontFamily()
{
$this->info = $this->getFontInfo();
return $this->info[1];
} // public function getFontFamily
/**
* function getFontSubFamily()
* #public
* #return 'Font Subfamily name' contained in the TTF 'name' table at index 2
*/
public function getFontSubFamily()
{
$this->info = $this->getFontInfo();
return $this->info[2];
} // public function getFontSubFamily
/**
* function getFontId()
* #public
* #return 'Unique font identifier' contained in the TTF 'name' table at index 3
*/
public function getFontId()
{
$this->info = $this->getFontInfo();
return $this->info[3];
} // public function getFontId
/**
* function getFullFontName()
* #public
* #return 'Full font name' contained in the TTF 'name' table at index 4
*/
public function getFullFontName()
{
$this->info = $this->getFontInfo();
return $this->info[4];
} // public function getFullFontName
/**
* function dec2ord()
* Used to lessen redundant calls to multiple functions.
* #protected
* #return object
*/
protected function dec2ord($dec)
{
return $this->dec2hex(ord($dec));
} // protected function dec2ord
/**
* function dec2hex()
* private function to perform Hexadecimal to decimal with proper padding.
* #protected
* #return object
*/
protected function dec2hex($dec)
{
return str_repeat('0', 2-strlen(($hex=strtoupper(dechex($dec))))) . $hex;
} // protected function dec2hex
/**
* function dec2hex()
* private function to perform Hexadecimal to decimal with proper padding.
* #protected
* #return object
*/
protected function exitClass($message)
{
echo $message;
exit;
} // protected function dec2hex
/**
* function dec2hex()
* private helper function to test in the file in question is a ttf.
* #protected
* #return object
*/
protected function is_ttf($file)
{
$ext = explode('.', $file);
$ext = $ext[count($ext)-1];
return preg_match("/ttf$/i",$ext) ? true : false;
} // protected function is_ttf
} // class ttfInfo
function getFontInfo($resource)
{
$ttfInfo = new ttfInfo;
$ttfInfo->setFontFile($resource);
return $ttfInfo->getFontInfo();
}
?>
Update 2021
Here is an updated version of the class with some fixes
https://github.com/HusamAamer/TTFInfo.git
Very similar to the previously posted answer... I've been using this class for a long time now.
class fontAttributes extends baseClass
{
// --- ATTRIBUTES ---
/**
* #access private
* #var string
*/
private $_fileName = NULL ; // Name of the truetype font file
/**
* #access private
* #var string
*/
private $_copyright = NULL ; // Copyright
/**
* #access private
* #var string
*/
private $_fontFamily = NULL ; // Font Family
/**
* #access private
* #var string
*/
private $_fontSubFamily = NULL ; // Font SubFamily
/**
* #access private
* #var string
*/
private $_fontIdentifier = NULL ; // Font Unique Identifier
/**
* #access private
* #var string
*/
private $_fontName = NULL ; // Font Name
/**
* #access private
* #var string
*/
private $_fontVersion = NULL ; // Font Version
/**
* #access private
* #var string
*/
private $_postscriptName = NULL ; // Postscript Name
/**
* #access private
* #var string
*/
private $_trademark = NULL ; // Trademark
// --- OPERATIONS ---
private function _returnValue($inString)
{
if (ord($inString) == 0) {
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($inString,"UTF-8","UTF-16");
} else {
return str_replace(chr(00),'',$inString);
}
} else {
return $inString;
}
} // function _returnValue()
/**
* #access public
* #return integer
*/
public function getCopyright()
{
return $this->_returnValue($this->_copyright);
} // function getCopyright()
/**
* #access public
* #return integer
*/
public function getFontFamily()
{
return $this->_returnValue($this->_fontFamily);
} // function getFontFamily()
/**
* #access public
* #return integer
*/
public function getFontSubFamily()
{
return $this->_returnValue($this->_fontSubFamily);
} // function getFontSubFamily()
/**
* #access public
* #return integer
*/
public function getFontIdentifier()
{
return $this->_returnValue($this->_fontIdentifier);
} // function getFontIdentifier()
/**
* #access public
* #return integer
*/
public function getFontName()
{
return $this->_returnValue($this->_fontName);
} // function getFontName()
/**
* #access public
* #return integer
*/
public function getFontVersion()
{
return $this->_returnValue($this->_fontVersion);
} // function getFontVersion()
/**
* #access public
* #return integer
*/
public function getPostscriptName()
{
return $this->_returnValue($this->_postscriptName);
} // function getPostscriptName()
/**
* #access public
* #return integer
*/
public function getTrademark()
{
return $this->_returnValue($this->_trademark);
} // function getTrademark()
/**
* Convert a big-endian word or longword value to an integer
*
* #access private
* #return integer
*/
private function _UConvert($bytesValue,$byteCount)
{
$retVal = 0;
$bytesLength = strlen($bytesValue);
for ($i=0; $i < $bytesLength; $i++) {
$tmpVal = ord($bytesValue{$i});
$t = pow(256,($byteCount-$i-1));
$retVal += $tmpVal*$t;
}
return $retVal;
} // function UConvert()
/**
* Convert a big-endian word value to an integer
*
* #access private
* #return integer
*/
private function _USHORT($stringValue) {
return $this->_UConvert($stringValue,2);
}
/**
* Convert a big-endian word value to an integer
*
* #access private
* #return integer
*/
private function _ULONG($stringValue) {
return $this->_UConvert($stringValue,4);
}
/**
* Read the Font Attributes
*
* #access private
* #return integer
*/
private function readFontAttributes() {
$fontHandle = fopen($this->_fileName, "rb");
// Read the file header
$TT_OFFSET_TABLE = fread($fontHandle, 12);
$uMajorVersion = $this->_USHORT(substr($TT_OFFSET_TABLE,0,2));
$uMinorVersion = $this->_USHORT(substr($TT_OFFSET_TABLE,2,2));
$uNumOfTables = $this->_USHORT(substr($TT_OFFSET_TABLE,4,2));
// $uSearchRange = $this->_USHORT(substr($TT_OFFSET_TABLE,6,2));
// $uEntrySelector = $this->_USHORT(substr($TT_OFFSET_TABLE,8,2));
// $uRangeShift = $this->_USHORT(substr($TT_OFFSET_TABLE,10,2));
// Check is this is a true type font and the version is 1.0
if ($uMajorVersion != 1 || $uMinorVersion != 0) {
fclose($fontHandle);
throw new Exception($this->_fileName.' is not a Truetype font file') ;
}
// Look for details of the name table
$nameTableFound = false;
for ($t=0; $t < $uNumOfTables; $t++) {
$TT_TABLE_DIRECTORY = fread($fontHandle, 16);
$szTag = substr($TT_TABLE_DIRECTORY,0,4);
if (strtolower($szTag) == 'name') {
// $uCheckSum = $this->_ULONG(substr($TT_TABLE_DIRECTORY,4,4));
$uOffset = $this->_ULONG(substr($TT_TABLE_DIRECTORY,8,4));
// $uLength = $this->_ULONG(substr($TT_TABLE_DIRECTORY,12,4));
$nameTableFound = true;
break;
}
}
if (!$nameTableFound) {
fclose($fontHandle);
throw new Exception('Can\'t find name table in '.$this->_fileName) ;
}
// Set offset to the start of the name table
fseek($fontHandle,$uOffset,SEEK_SET);
$TT_NAME_TABLE_HEADER = fread($fontHandle, 6);
// $uFSelector = $this->_USHORT(substr($TT_NAME_TABLE_HEADER,0,2));
$uNRCount = $this->_USHORT(substr($TT_NAME_TABLE_HEADER,2,2));
$uStorageOffset = $this->_USHORT(substr($TT_NAME_TABLE_HEADER,4,2));
$attributeCount = 0;
for ($a=0; $a < $uNRCount; $a++) {
$TT_NAME_RECORD = fread($fontHandle, 12);
$uNameID = $this->_USHORT(substr($TT_NAME_RECORD,6,2));
if ($uNameID <= 7) {
// $uPlatformID = $this->_USHORT(substr($TT_NAME_RECORD,0,2));
$uEncodingID = $this->_USHORT(substr($TT_NAME_RECORD,2,2));
// $uLanguageID = $this->_USHORT(substr($TT_NAME_RECORD,4,2));
$uStringLength = $this->_USHORT(substr($TT_NAME_RECORD,8,2));
$uStringOffset = $this->_USHORT(substr($TT_NAME_RECORD,10,2));
if ($uStringLength > 0) {
$nPos = ftell($fontHandle);
fseek($fontHandle,$uOffset + $uStringOffset + $uStorageOffset,SEEK_SET);
$testValue = fread($fontHandle, $uStringLength);
if (trim($testValue) > '') {
switch ($uNameID) {
case 0 : if ($this->_copyright == NULL) {
$this->_copyright = $testValue;
$attributeCount++;
}
break;
case 1 : if ($this->_fontFamily == NULL) {
$this->_fontFamily = $testValue;
$attributeCount++;
}
break;
case 2 : if ($this->_fontSubFamily == NULL) {
$this->_fontSubFamily = $testValue;
$attributeCount++;
}
break;
case 3 : if ($this->_fontIdentifier == NULL) {
$this->_fontIdentifier = $testValue;
$attributeCount++;
}
break;
case 4 : if ($this->_fontName == NULL) {
$this->_fontName = $testValue;
$attributeCount++;
}
break;
case 5 : if ($this->_fontVersion == NULL) {
$this->_fontVersion = $testValue;
$attributeCount++;
}
break;
case 6 : if ($this->_postscriptName == NULL) {
$this->_postscriptName = $testValue;
$attributeCount++;
}
break;
case 7 : if ($this->_trademark == NULL) {
$this->_trademark = $testValue;
$attributeCount++;
}
break;
}
}
fseek($fontHandle,$nPos,SEEK_SET);
}
}
if ($attributeCount > 7) {
break;
}
}
fclose($fontHandle);
return true;
}
/**
* #access constructor
* #return void
*/
function __construct($fileName='') {
if ($fileName == '') {
throw new Exception('Font File has not been specified') ;
}
$this->_fileName = $fileName;
if (!file_exists($this->_fileName)) {
throw new Exception($this->_fileName.' does not exist') ;
} elseif (!is_readable($this->_fileName)) {
throw new Exception($this->_fileName.' is not a readable file') ;
}
return $this->readFontAttributes();
} // function constructor()
} /* end of class fontAttributes */
Why reinvent the wheel when the fine people at DOMPDF project has already done the work for you? Take a look at php-font-lib # https://github.com/PhenX/php-font-lib. This has all the features that you have asked for and supports other font formats as well. Look at the demo UI # http://pxd.me/php-font-lib/www/font_explorer.html to get an idea about what kind of information you can get from this library.