src/CallUrlModel/WeatherModelTrait.php
<?php
/**
* Showing off a standard class with methods and properties.
*/
namespace Erjh17\CallUrlModel;
/**
* A trait implementing WeatherModelTrait.
*/
trait WeatherModelTrait
{
/**
* Class handling logic for fetching and parsing weather data from API calls.
*
* @var int $ip The ip address.
* @var string $message The message.
* @var boolean $valid If the ip address is valid.
* @var string $host The ip adress' host.
*/
private $position;
private $darkSkyUrl;
private $currently;
private $hourly;
private $daily;
private $pastDays;
private $darkskykey;
public static $dateFormat = "%e %B %Y";
public static $timeFormat = "%R";
public static $dayFormat = "%A";
abstract public function getInfo();
abstract public function getGeoInfo();
abstract public function pushInfo($result, $keys);
abstract public function getZoomLevel();
abstract public function setErrorMessage($msg);
abstract public function fillInfo($result, $keys);
/**
* Sets darkskykey property.
*
* @param string $url darksky url.
*/
public function setDarkskyUrl($url)
{
$this->darkSkyUrl = $url;
}
/**
* Sets darkskykey property.
*
* @param string $key darksky key.
*/
public function setDarkskyKey($key)
{
$this->darkskykey = $key;
}
/**
* Get darkskykey property.
*
* @return string $key darksky key.
*/
public function getDarkskyKey()
{
return $this->darkskykey;
}
/**
* Returns specific fetched key properties.
*
* @return array Weather data
*/
public function getWeatherInfo()
{
if ($this->currently !== null) {
return array_merge(
$this->getInfo(),
$this->getGeoInfo(),
array(
"pos" => $this->ipAddress,
"positionName" => $this->getPosition(),
"currently" => $this->currently(),
"hours" => $this->hourly(),
"days" => $this->daily(),
"pastDays" => $this->pastDays(),
"script" => $this->generateScript()
)
);
} else {
return array_merge(
$this->getInfo(),
array(
"pos" => $this->ipAddress
)
);
}
}
/**
* Sets the position property according to available properties.
*
* @return string Position string
*/
public function getPosition()
{
$positionName = $this->ipAddress;
if ($this->city) {
$placeNames = array($this->city);
if ($this->country_name) {
array_push($placeNames, $this->country_name);
}
$positionName = implode(", ", $placeNames);
} elseif ($this->latitude && $this->longitude) {
$positionName = $this->latitude . ", " . $this->longitude;
}
return $positionName;
}
/**
* Parses and returns the weather data for the current day
*
* @return array Parsed weather data.
*/
public function currently()
{
$currently = [];
setlocale(LC_ALL, 'sv_SV');
if ($this->currently && $this->currently["time"]) {
$currently = $this->pushInfo(
$this->currently,
[
"weekday",
"date",
"timeofday",
"icon",
"temperature",
"apparentTemperature",
"summary",
"windSpeed",
"precipProbability",
"pressure"
]
);
$time = $this->currently["time"];
$localdate = strftime(self::$dateFormat, $time);
$localtime = strftime(self::$timeFormat, $time);
$weekday = strftime(self::$dayFormat, $time);
$currently["weekday"] = ucfirst($weekday);
$currently["date"] = ucfirst($localdate);
$currently["timeofday"] = ucfirst($localtime);
}
return $currently;
}
public function generateScript()
{
$zoomLevel = $this->getZoomLevel();
$latitude = str_replace(",", ".", $this->latitude);
$longitude = str_replace(",", ".", $this->longitude);
$zLevel = $zoomLevel["zoomLevel"];
$radius = $zoomLevel["radius"];
$script = " window.addEventListener('load', function() {".
" window.initMap($longitude, $latitude, $zLevel, $radius);".
" var skycons = new Skycons({'color': 'white'});";
$icon = $this->currently['icon'];
$script .= " skycons.add('icon1', '$icon');";
foreach ($this->daily["data"] as $day) {
$time = $day['time'];
$icon = $day['icon'];
$script .= "skycons.add('icon$time', '$icon');";
}
$script .= " skycons.play();".
" });";
return $script;
}
/**
* Parses and returns the weather data for coming hours
*
* @return array Parsed weather data.
*/
public function hourly()
{
$hourly = [];
if ($this->hourly && isset($this->hourly["data"])) {
$this->hourly["data"] = array_slice($this->hourly["data"], 0, 12);
$hours = count($this->hourly["data"]);
for ($i=0; $i < $hours; $i++) {
setlocale(LC_ALL, 'sv_SV');
$time = $this->hourly["data"][$i]["time"];
if ($time) {
$this->parseDate("hourly", $i, $time);
$weekday = strftime(self::$dayFormat, $time);
$weeknr = strftime("%w", $time);
$hourly["days"][$weeknr]["hours"][$i] = $this->pushInfo(
$this->hourly["data"][$i],
[
"icon",
"timeofday",
"summary",
"temperature",
"apparentTemperature",
"date",
"weekday",
"timeofday"
]
);
$hourly["days"][$weeknr]["day"] = ucfirst($weekday);
}
}
}
return $hourly;
}
/**
* Parses and returns the weather data for the past days
*
* @return array Parsed weather data.
*/
public function pastDays()
{
$pastDays = [];
if ($this->pastDays["data"]) {
setlocale(LC_ALL, 'sv_SV');
$pastDayCount = count($this->pastDays["data"]);
for ($i=0; $i < $pastDayCount; $i++) {
$pastDaysTime = $this->pastDays["data"][$i]["time"];
if ($pastDaysTime) {
$this->parseDate("pastDays", $i, $pastDaysTime);
$pastDays[$i] = $this->pushInfo(
$this->pastDays["data"][$i],
[
"icon",
"weekday",
"date",
"summary",
"temperatureMax",
"apparentTemperatureMax",
"temperatureMin",
"apparentTemperatureMin",
"time"
]
);
}
}
}
return $pastDays;
}
/**
* Parses weather data and creates date and time data and returns them.
*
* @param string $arr string representing the property
* to be called from '$this'
* @param integer $i array index in target data object
* @param int $time Unix time integer
*
* @return void
*/
public function parseDate($arr, $i, $time)
{
$localdate = strftime(self::$dateFormat, $time);
$localtime = strftime(self::$timeFormat, $time);
$weekday = strftime(self::$dayFormat, $time);
$this->$arr["data"][$i]["date"] = $localdate;
$this->$arr["data"][$i]["weekday"] = ucfirst($weekday);
$this->$arr["data"][$i]["timeofday"] = $localtime;
$this->$arr["days"][strftime("%w", $time)]["hours"][$i] = $this->$arr["data"][$i];
$this->$arr["days"][strftime("%w", $time)]["day"] = ucfirst($weekday);
}
/**
* Parses and returns the weather data for the coming days
*
* @return array Parsed weather data.
*/
public function daily()
{
$days = [];
if ($this->daily) {
setlocale(LC_ALL, 'sv_SV');
$comingDays = array_slice($this->daily["data"], 1, 30);
foreach ($comingDays as $i => $data) {
if ($data["time"]) {
$this->parseDate("daily", $i, $data["time"]);
$days[$i] = $this->pushInfo(
$this->daily["data"][$i],
[
"weekday",
"date",
"icon",
"summary",
"temperatureMax",
"apparentTemperatureMax",
"temperatureMin",
"apparentTemperatureMin",
"time"
]
);
}
}
}
return $days;
}
/**
* Creates array containing dates ranging 30 days back
*
* @return array Dates
*/
public function calculateTimeMachine()
{
$days = array();
for ($i=1; $i < 31; $i++) {
$date = date('c', strtotime("-$i days"));
array_push($days, strtotime($date));
}
return $days;
}
/**
* Creates the arguments to go into the batch call
*
* @return array Array containing urls, parameters and query strings
*/
public function buildArgs()
{
$time = $this->calculateTimeMachine();
$urls = array($this->darkSkyUrl);
$params = array(
array($this->getDarkskyKey(), $this->latitude . "," . $this->longitude)
);
$queries = array(
array("lang" => "sv", "units" => "si")
);
// var_dump($this->darkSkyUrl);
foreach ($time as $day) {
array_push($urls, $this->darkSkyUrl);
array_push(
$params,
array(
$this->getDarkskyKey(),
$this->latitude . "," . $this->longitude . "," . $day
)
);
array_push(
$queries,
array(
"lang" => "sv",
"units" => "si",
"exclude" => "currently,flags,hourly"
)
);
}
return [
"urls" => $urls,
"params" => $params,
"queries" => $queries
];
}
/**
* Batch API-calls to get weather data
*
* @return array Weather data
*/
public function fetchWeatherInfo()
{
if ($this->latitude && $this->latitude) {
$cUrl = $this->di->get("callurl");
$args = $this->buildArgs();
$apiResult = $cUrl->fetchConcurrently(
$args["urls"],
$args["params"],
$args["queries"]
);
if (isset($apiResult[0]["error"])) {
$this->setErrorMessage("DarkSkyError: " . $apiResult[0]['error']);
}
$pastDays = array("data" => []);
$resultCount = count($apiResult);
for ($i=1; $i<$resultCount; $i++) {
if ($apiResult[$i] && isset($apiResult[$i]["daily"]["data"][0])) {
array_push($pastDays["data"], $apiResult[$i]["daily"]["data"][0]);
}
}
// var_dump($apiResult);
if ($apiResult[0]) {
$this->fillInfo(
array_merge($apiResult[0], array("pastDays" => $pastDays)),
[
"currently",
"hourly",
"daily",
"pastDays"
]
);
} else {
$this->setErrorMessage("DarkSkyError: daily usage limit exceeded");
}
}
return $this->getWeatherInfo();
}
}