scratch

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 86  →  ?path2? @ 87
/vendor/fusonic/opengraph/src/Consumer.php
@@ -0,0 +1,140 @@
<?php
 
namespace Fusonic\OpenGraph;
 
use Fusonic\Linq\Linq;
use Fusonic\OpenGraph\Objects\ObjectBase;
use Fusonic\OpenGraph\Objects\Website;
use GuzzleHttp\Adapter\AdapterInterface;
use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;
 
/**
* Consumer that extracts Open Graph data from either a URL or a HTML string.
*/
class Consumer
{
private $client;
 
/**
* When enabled, crawler will read content of title and meta description if no
* Open Graph data is provided by target page.
*
* @var bool
*/
public $useFallbackMode = false;
 
/**
* When enabled, crawler will throw exceptions for some crawling errors like unexpected
* Open Graph elements.
*
* @var bool
*/
public $debug = false;
 
/**
* @param AdapterInterface $adapter Guzzle adapter to use for making HTTP requests.
* @param array $config Optional Guzzle config overrides.
*/
public function __construct(AdapterInterface $adapter = null, array $config = [])
{
$config = array_replace_recursive(['adapter' => $adapter], $config);
 
$this->client = new Client($config);
}
 
/**
* Fetches HTML content from the given URL and then crawls it for Open Graph data.
*
* @param string $url URL to be crawled.
*
* @return Website
*/
public function loadUrl($url)
{
// Fetch HTTP content using Guzzle
$response = $this->client->get($url);
 
return $this->loadHtml($response->getBody()->__toString(), $url);
}
 
/**
* Crawls the given HTML string for OpenGraph data.
*
* @param string $html HTML string, usually whole content of crawled web resource.
* @param string $fallbackUrl URL to use when fallback mode is enabled.
*
* @return ObjectBase
*/
public function loadHtml($html, $fallbackUrl = null)
{
// Extract all data that can be found
$page = $this->extractOpenGraphData($html);
 
// Use the user's URL as fallback
if ($this->useFallbackMode && $page->url === null) {
$page->url = $fallbackUrl;
}
 
// Return result
return $page;
}
 
private function extractOpenGraphData($content)
{
$crawler = new Crawler($content);
 
$properties = [];
foreach(['name', 'property'] as $t)
{
// Get all meta-tags starting with "og:"
$ogMetaTags = $crawler->filter("meta[{$t}^='og:']");
// Create clean property array
$props = Linq::from($ogMetaTags)
->select(
function (\DOMElement $tag) use ($t) {
$name = strtolower(trim($tag->getAttribute($t)));
$value = trim($tag->getAttribute("content"));
return new Property($name, $value);
}
)
->toArray();
$properties = array_merge($properties, $props);
}
// Create new object of the correct type
$typeProperty = Linq::from($properties)
->firstOrNull(
function (Property $property) {
return $property->key === Property::TYPE;
}
);
switch ($typeProperty !== null ? $typeProperty->value : null) {
default:
$object = new Website();
break;
}
 
// Assign all properties to the object
$object->assignProperties($properties, $this->debug);
 
// Fallback for title
if ($this->useFallbackMode && !$object->title) {
$titleElement = $crawler->filter("title")->first();
if ($titleElement) {
$object->title = trim($titleElement->text());
}
}
 
// Fallback for description
if ($this->useFallbackMode && !$object->description) {
$descriptionElement = $crawler->filter("meta[property='description']")->first();
if ($descriptionElement) {
$object->description = trim($descriptionElement->attr("content"));
}
}
 
return $object;
}
}
/vendor/fusonic/opengraph/src/Elements/Audio.php
@@ -0,0 +1,67 @@
<?php
 
namespace Fusonic\OpenGraph\Elements;
 
use Fusonic\OpenGraph\Property;
 
/**
* An Open Graph audio element.
*/
class Audio extends ElementBase
{
/**
* The URL of an audio resource associated with the object.
*
* @var string
*/
public $url;
 
/**
* An alternate URL to use if an audio resource requires HTTPS.
*
* @var string
*/
public $secureUrl;
 
/**
* The MIME type of an audio resource associated with the object.
*
* @var type
*/
public $type;
 
/**
* @param string $url URL to the audio file.
*/
public function __construct($url)
{
parent::__construct();
 
$this->url = $url;
}
 
/**
* Gets all properties set on this element.
*
* @return array|Property[]
*/
public function getProperties()
{
$properties = [];
 
// URL must precede all other properties
if ($this->url !== null) {
$properties[] = new Property(Property::AUDIO_URL, $this->url);
}
 
if ($this->secureUrl !== null) {
$properties[] = new Property(Property::AUDIO_SECURE_URL, $this->secureUrl);
}
 
if ($this->type !== null) {
$properties[] = new Property(Property::AUDIO_TYPE, $this->type);
}
 
return $properties;
}
}
/vendor/fusonic/opengraph/src/Elements/ElementBase.php
@@ -0,0 +1,20 @@
<?php
 
namespace Fusonic\OpenGraph\Elements;
 
/**
* Abstract base class for all OpenGraph elements (e.g. images, videos etc.)
*/
abstract class ElementBase
{
protected function __construct()
{
}
 
/**
* Gets all properties set on this element.
*
* @return array|Property[]
*/
abstract public function getProperties();
}
/vendor/fusonic/opengraph/src/Elements/Image.php
@@ -0,0 +1,100 @@
<?php
 
namespace Fusonic\OpenGraph\Elements;
 
use Fusonic\OpenGraph\Property;
 
/**
* An Open Graph image element.
*/
class Image extends ElementBase
{
/**
* The URL of an image resource associated with the object.
*
* @var string
*/
public $url;
 
/**
* An alternate URL to use if an image resource requires HTTPS.
*
* @var string
*/
public $secureUrl;
 
/**
* The MIME type of an image resource.
*
* @var type
*/
public $type;
 
/**
* The width of an image resource in pixels.
*
* @var int
*/
public $width;
 
/**
* The height of an image resource in pixels.
*
* @var int
*/
public $height;
 
/**
* Whether the image is user-generated or not.
*
* @var bool
*/
public $userGenerated;
 
/**
* @param string $url URL to the image file.
*/
public function __construct($url)
{
parent::__construct();
 
$this->url = $url;
}
 
/**
* Gets all properties set on this element.
*
* @return array|Property[]
*/
public function getProperties()
{
$properties = [];
 
// URL must precede all other properties
if ($this->url !== null) {
$properties[] = new Property(Property::IMAGE_URL, $this->url);
}
 
if ($this->height !== null) {
$properties[] = new Property(Property::IMAGE_HEIGHT, $this->height);
}
 
if ($this->secureUrl !== null) {
$properties[] = new Property(Property::IMAGE_SECURE_URL, $this->secureUrl);
}
 
if ($this->type !== null) {
$properties[] = new Property(Property::IMAGE_TYPE, $this->type);
}
 
if ($this->width !== null) {
$properties[] = new Property(Property::IMAGE_WIDTH, $this->width);
}
 
if ($this->userGenerated !== null) {
$properties[] = new Property(Property::IMAGE_USER_GENERATED, $this->userGenerated);
}
 
return $properties;
}
}
/vendor/fusonic/opengraph/src/Elements/Video.php
@@ -0,0 +1,89 @@
<?php
 
namespace Fusonic\OpenGraph\Elements;
 
use Fusonic\OpenGraph\Property;
 
/**
* An OpenGraph video element.
*/
class Video extends ElementBase
{
/**
* The URL of a video resource associated with the object.
*
* @var string
*/
public $url;
 
/**
* An alternate URL to use if a video resource requires HTTPS.
*
* @var string
*/
public $secureUrl;
 
/**
* The MIME type of a video resource associated with the object.
*
* @var type
*/
public $type;
 
/**
* The width of a video resource associated with the object in pixels.
*
* @var int
*/
public $width;
 
/**
* The height of a video resource associated with the object in pixels.
*
* @var int
*/
public $height;
 
/**
* @param string $url URL to the video.
*/
public function __construct($url)
{
parent::__construct();
 
$this->url = $url;
}
 
/**
* Gets all properties set on this element.
*
* @return array|Property[]
*/
public function getProperties()
{
$properties = [];
 
// URL must precede all other properties
if ($this->url !== null) {
$properties[] = new Property(Property::VIDEO_URL, $this->url);
}
 
if ($this->height !== null) {
$properties[] = new Property(Property::VIDEO_HEIGHT, $this->height);
}
 
if ($this->secureUrl !== null) {
$properties[] = new Property(Property::VIDEO_SECURE_URL, $this->secureUrl);
}
 
if ($this->type !== null) {
$properties[] = new Property(Property::VIDEO_TYPE, $this->type);
}
 
if ($this->width !== null) {
$properties[] = new Property(Property::VIDEO_WIDTH, $this->width);
}
 
return $properties;
}
}
/vendor/fusonic/opengraph/src/Objects/ObjectBase.php
@@ -0,0 +1,370 @@
<?php
 
namespace Fusonic\OpenGraph\Objects;
 
use Fusonic\Linq\Linq;
use Fusonic\OpenGraph\Elements\Audio;
use Fusonic\OpenGraph\Elements\Image;
use Fusonic\OpenGraph\Elements\Video;
use Fusonic\OpenGraph\Property;
 
/**
* Abstract base class for all Open Graph objects (website, video, ...)
*/
abstract class ObjectBase
{
/**
* An array of audio resources attached to the object.
*
* @var array|Audio[]
*/
public $audios = [];
 
/**
* A short description of the object.
*
* @var string
*/
public $description;
 
/**
* The word that appears before the object's title in a sentence. This is an list of words from 'a', 'an', 'the',
* ' "" ', or 'auto'. If 'auto' is chosen, the consumer of the object will chose between 'a' or 'an'. The default is
* the blank, "".
*
* @var string
*/
public $determiner;
 
/**
* An array of images attached to the object.
*
* @var array|Image[]
*/
public $images = [];
 
/**
* The locale that the object's tags are marked up in, in the format language_TERRITORY.
*
* @var string
*/
public $locale;
 
/**
* An array of alternate locales in which the resource is available.
*
* @var array|string[]
*/
public $localeAlternate = [];
 
/**
* @var bool
*/
public $richAttachment;
 
/**
* An array of URLs of related resources.
*
* @var array|string[]
*/
public $seeAlso = [];
 
/**
* The name of the web site upon which the object resides.
*
* @var string
*/
public $siteName;
 
/**
* The title of the object as it should appear in the graph.
*
* @var string
*/
public $title;
 
/**
* The type of the object, such as 'article'.
*
* @var string
*/
public $type;
 
/**
* The time when the object was last updated.
*
* @var \DateTime
*/
public $updatedTime;
 
/**
* The canonical URL of the object, used as its ID in the graph.
*
* @var string
*/
public $url;
 
/**
* An array of videos attached to the object.
*
* @var array|Video[]
*/
public $videos = [];
 
public function __construct()
{
}
 
/**
* Assigns all properties given to the this Object instance.
*
* @param array|Property[] $properties Array of all properties to assign.
* @param bool $debug Throw exceptions when parsing or not.
*
* @throws \UnexpectedValueException
*/
public function assignProperties(array $properties, $debug = false)
{
foreach ($properties as $property) {
$name = $property->key;
$value = $property->value;
 
switch($name) {
case Property::AUDIO:
case Property::AUDIO_URL:
$this->audios[] = new Audio($value);
break;
case Property::AUDIO_SECURE_URL:
case Property::AUDIO_TYPE:
if (count($this->audios) > 0) {
$this->handleAudioAttribute($this->audios[count($this->audios) - 1], $name, $value);
} elseif ($debug) {
throw new \UnexpectedValueException(
sprintf(
"Found '%s' property but no audio was found before.",
$name
)
);
}
break;
case Property::DESCRIPTION:
if ($this->description === null) {
$this->description = $value;
}
break;
case Property::DETERMINER:
if ($this->determiner === null) {
$this->determiner = $value;
}
break;
case Property::IMAGE:
case Property::IMAGE_URL:
$this->images[] = new Image($value);
break;
case Property::IMAGE_HEIGHT:
case Property::IMAGE_SECURE_URL:
case Property::IMAGE_TYPE:
case Property::IMAGE_WIDTH:
case Property::IMAGE_USER_GENERATED:
if (count($this->images) > 0) {
$this->handleImageAttribute($this->images[count($this->images) - 1], $name, $value);
} elseif ($debug) {
throw new \UnexpectedValueException(
sprintf(
"Found '%s' property but no image was found before.",
$name
)
);
}
break;
case Property::LOCALE:
if ($this->locale === null) {
$this->locale = $value;
}
break;
case Property::LOCALE_ALTERNATE:
$this->localeAlternate[] = $value;
break;
case Property::RICH_ATTACHMENT:
$this->richAttachment = $this->convertToBoolean($value);
break;
case Property::SEE_ALSO:
$this->seeAlso[] = $value;
break;
case Property::SITE_NAME:
if ($this->siteName === null) {
$this->siteName = $value;
}
break;
case Property::TITLE:
if ($this->title === null) {
$this->title = $value;
}
break;
case Property::UPDATED_TIME:
if ($this->updatedTime === null && strtotime($value) !== false) {
$this->updatedTime = $this->convertToDateTime($value);
}
break;
case Property::URL:
if ($this->url === null) {
$this->url = $value;
}
break;
case Property::VIDEO:
case Property::VIDEO_URL:
$this->videos[] = new Video($value);
break;
case Property::VIDEO_HEIGHT:
case Property::VIDEO_SECURE_URL:
case Property::VIDEO_TYPE:
case Property::VIDEO_WIDTH:
if (count($this->videos) > 0) {
$this->handleVideoAttribute($this->videos[count($this->videos) - 1], $name, $value);
} elseif ($debug) {
throw new \UnexpectedValueException(
sprintf(
"Found '%s' property but no video was found before.",
$name
)
);
}
}
}
}
 
private function handleImageAttribute(Image $element, $name, $value)
{
switch($name)
{
case Property::IMAGE_HEIGHT:
$element->height = (int)$value;
break;
case Property::IMAGE_WIDTH:
$element->width = (int)$value;
break;
case Property::IMAGE_TYPE:
$element->type = $value;
break;
case Property::IMAGE_SECURE_URL:
$element->secureUrl = $value;
break;
case Property::IMAGE_USER_GENERATED:
$element->userGenerated = $this->convertToBoolean($value);
break;
}
}
 
private function handleVideoAttribute(Video $element, $name, $value)
{
switch($name)
{
case Property::VIDEO_HEIGHT:
$element->height = (int)$value;
break;
case Property::VIDEO_WIDTH:
$element->width = (int)$value;
break;
case Property::VIDEO_TYPE:
$element->type = $value;
break;
case Property::VIDEO_SECURE_URL:
$element->secureUrl = $value;
break;
}
}
 
private function handleAudioAttribute(Audio $element, $name, $value)
{
switch($name)
{
case Property::AUDIO_TYPE:
$element->type = $value;
break;
case Property::AUDIO_SECURE_URL:
$element->secureUrl = $value;
break;
}
}
 
protected function convertToDateTime($value)
{
return new \DateTime($value);
}
 
protected function convertToBoolean($value)
{
switch(strtolower($value))
{
case "1":
case "true":
return true;
default:
return false;
}
}
 
/**
* Gets all properties set on this object.
*
* @return array|Property[]
*/
public function getProperties()
{
$properties = [];
 
foreach ($this->audios as $audio) {
$properties = array_merge($properties, $audio->getProperties());
}
 
if ($this->description !== null) {
$properties[] = new Property(Property::DESCRIPTION, $this->description);
}
 
if ($this->determiner !== null) {
$properties[] = new Property(Property::DETERMINER, $this->determiner);
}
 
foreach ($this->images as $image) {
$properties = array_merge($properties, $image->getProperties());
}
 
if ($this->locale !== null) {
$properties[] = new Property(Property::LOCALE, $this->locale);
}
 
foreach ($this->localeAlternate as $locale) {
$properties[] = new Property(Property::LOCALE_ALTERNATE, $locale);
}
 
if ($this->richAttachment !== null) {
$properties[] = new Property(Property::RICH_ATTACHMENT, (int)$this->richAttachment);
}
 
foreach ($this->seeAlso as $seeAlso) {
$properties[] = new Property(Property::SEE_ALSO, $seeAlso);
}
 
if ($this->siteName !== null) {
$properties[] = new Property(Property::SITE_NAME, $this->siteName);
}
 
if ($this->type !== null) {
$properties[] = new Property(Property::TYPE, $this->type);
}
 
if ($this->updatedTime !== null) {
$properties[] = new Property(Property::UPDATED_TIME, $this->updatedTime->format("c"));
}
 
if ($this->url !== null) {
$properties[] = new Property(Property::URL, $this->url);
}
 
foreach ($this->videos as $video) {
$properties = array_merge($properties, $video->getProperties());
}
 
return $properties;
}
}
/vendor/fusonic/opengraph/src/Objects/Website.php
@@ -0,0 +1,21 @@
<?php
 
namespace Fusonic\OpenGraph\Objects;
 
/**
* This object type represents a website. It is a simple object type and uses only common Open Graph properties. For
* specific pages within a website, the article object type should be used.
*
* https://developers.facebook.com/docs/reference/opengraph/object-type/website/
*/
class Website extends ObjectBase
{
const TYPE = "website";
 
public function __construct()
{
parent::__construct();
 
$this->type = self::TYPE;
}
}
/vendor/fusonic/opengraph/src/Property.php
@@ -0,0 +1,58 @@
<?php
 
namespace Fusonic\OpenGraph;
 
/**
* Class holding data for a single Open Graph property on a web page.
*/
class Property
{
const AUDIO = "og:audio";
const AUDIO_SECURE_URL = "og:audio:secure_url";
const AUDIO_TYPE = "og:audio:type";
const AUDIO_URL = "og:audio:url";
const DESCRIPTION = "og:description";
const DETERMINER = "og:determiner";
const IMAGE = "og:image";
const IMAGE_HEIGHT = "og:image:height";
const IMAGE_SECURE_URL = "og:image:secure_url";
const IMAGE_TYPE = "og:image:type";
const IMAGE_URL = "og:image:url";
const IMAGE_WIDTH = "og:image:width";
const IMAGE_USER_GENERATED = "og:image:user_generated";
const LOCALE = "og:locale";
const LOCALE_ALTERNATE = "og:locale:alternate";
const RICH_ATTACHMENT = "og:rich_attachment";
const SEE_ALSO = "og:see_also";
const SITE_NAME = "og:site_name";
const TITLE = "og:title";
const TYPE = "og:type";
const UPDATED_TIME = "og:updated_time";
const URL = "og:url";
const VIDEO = "og:video";
const VIDEO_HEIGHT = "og:video:height";
const VIDEO_SECURE_URL = "og:video:secure_url";
const VIDEO_TYPE = "og:video:type";
const VIDEO_URL = "og:video:url";
const VIDEO_WIDTH = "og:video:width";
 
/**
* Key of the property without "og:" prefix.
*
* @var string
*/
public $key;
 
/**
* Value of the property.
*
* @var string
*/
public $value;
 
public function __construct($key, $value)
{
$this->key = $key;
$this->value = $value;
}
}
/vendor/fusonic/opengraph/src/Publisher.php
@@ -0,0 +1,62 @@
<?php
 
namespace Fusonic\OpenGraph;
 
use Fusonic\OpenGraph\Objects\ObjectBase;
 
/**
* Class for generating Open Graph tags from objects.
*/
class Publisher
{
const DOCTYPE_HTML5 = 1;
const DOCTYPE_XHTML = 2;
 
/**
* Defines the style in which HTML tags should be written. Use one of Publisher::DOCTYPE_HTML5 or
* Publisher::DOCTYPE_XHTML.
*
* @var int
*/
public $doctype = self::DOCTYPE_HTML5;
 
public function __construct()
{
}
 
public function generateHtml(ObjectBase $object)
{
$html = "";
$format = "<meta property=\"%s\" content=\"%s\"" . ($this->doctype == self::DOCTYPE_XHTML ? " />" : ">");
 
foreach ($object->getProperties() as $property) {
if ($html !== "") {
$html .= "\n";
}
 
if ($property->value === null) {
continue;
} elseif ($property->value instanceof \DateTime) {
$value = $property->value->format("c");
} elseif (is_object($property->value)) {
throw new \UnexpectedValueException(
sprintf(
"Cannot handle value of type '%0' for property '%1'.",
get_class($property->value),
$property->key
)
);
} elseif ($property->value === true) {
$value = "1";
} elseif ($property->value === false) {
$value = "0";
} else {
$value = (string)$property->value;
}
 
$html .= sprintf($format, $property->key, htmlspecialchars($value));
}
 
return $html;
}
}