aura.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. namespace Grav\Plugin\Aura;
  3. use Grav\Common\Grav;
  4. use Grav\Common\Page\Page;
  5. use Grav\Plugin\AuraAuthorsPlugin;
  6. class Aura
  7. {
  8. private $org;
  9. private $website;
  10. public $webpage;
  11. private $person;
  12. private $grav;
  13. private $otherPresence = array(
  14. 'facebook-url',
  15. 'instagram-url',
  16. 'linkedin-url',
  17. 'pinterest-url',
  18. 'youtube-url',
  19. 'wikipedia-url',
  20. 'website-url',
  21. );
  22. /**
  23. * Initializes Aura variables for the page
  24. *
  25. * @param object $page
  26. *
  27. */
  28. public function __construct(Page $page)
  29. {
  30. $this->grav = $cache = Grav::instance();
  31. /*
  32. * Organization
  33. */
  34. $this->org = new Organization();
  35. $this->org->url = (string)$this->grav['config']->get('plugins.aura.org-url');
  36. $this->org->id = $this->org->url . '#organization';
  37. $this->org->name = $this->grav['config']->get('plugins.aura.org-name');
  38. // Org SameAs
  39. $sameAs = array();
  40. foreach ($this->otherPresence as $platform) {
  41. $key = 'plugins.aura.org-' . $platform;
  42. if ($this->grav['config']->get($key)) {
  43. $sameAs[] = $this->grav['config']->get($key);
  44. }
  45. }
  46. $key = 'plugins.aura.' . 'org-twitter-user';
  47. if ($this->grav['config']->get($key)) {
  48. $sameAs[] = 'https://twitter.com/' . $this->grav['config']->get($key);
  49. }
  50. if (!empty($sameAs)) {
  51. $this->org->sameAs = $sameAs;
  52. }
  53. // Org Logo
  54. if ($this->grav['config']->get('plugins.aura.org-logo')) {
  55. $imageArray = $this->grav['config']->get('plugins.aura.org-logo');
  56. $firstImage = reset($imageArray);
  57. $imagePath = ROOT_DIR . $firstImage['path'];
  58. if (file_exists($imagePath)) {
  59. $size = getimagesize($imagePath);
  60. $this->org->logo = new Image();
  61. $this->org->logo->url = $this->grav['base_url_absolute'] . '/' . $firstImage['path'];
  62. $this->org->logo->id = $this->org->url . '#logo';
  63. $this->org->logo->width = $size[0];
  64. $this->org->logo->height = $size[1];
  65. $this->org->logo->caption = $this->org->name;
  66. $this->org->logo->type = $size['mime'];
  67. }
  68. }
  69. /*
  70. * Website
  71. */
  72. $this->website = new WebSite;
  73. $this->website->url = $this->grav['base_url_absolute'];
  74. $this->website->id = $this->website->url . '#website';
  75. $this->website->name = $this->grav['config']->get('site.title');
  76. /*
  77. * Webpage
  78. */
  79. $this->webpage = new WebPage;
  80. $this->webpage->url = $page->url(true);
  81. $this->webpage->id = $this->webpage->url . '#webpage';
  82. $this->webpage->title = $page->title() . ' | ' . $this->grav['config']->get('site.title');
  83. $header = $page->header();
  84. if ((isset($header->aura['description'])) && ($header->aura['description'] != '')) {
  85. $this->webpage->description = (string)$header->aura['description'];
  86. }
  87. if ((isset($header->language)) and ($header->language != '')) {
  88. $this->webpage->language = $header->language;
  89. } else {
  90. $this->webpage->language = $this->grav['language']->getActive();
  91. if (!$this->webpage->language) {
  92. $this->webpage->language = $this->grav['config']->get('site.default_lang');
  93. }
  94. }
  95. $datePublishedRaw = time();
  96. if ($page->publishDate()) {
  97. $datePublishedRaw = $page->publishDate();
  98. } else if ($page->date()) {
  99. $datePublishedRaw = $page->date();
  100. } else if ($page->modified()) {
  101. $datePublishedRaw = $page->modified();
  102. }
  103. $dateModifiedRaw = $page->modified() ? $page->modified() : time();
  104. $this->webpage->datePublished = date("c", $datePublishedRaw);
  105. $this->webpage->dateModified = date("c", $dateModifiedRaw);
  106. // Webpage Image
  107. $filename = false;
  108. if ((isset($header->aura['image'])) && ($header->aura['image'] != '')) {
  109. $filename = $header->aura['image'];
  110. } else if (isset($header->media_order) && ($header->media_order != '')) {
  111. $images = explode(',', $header->media_order);
  112. if ((is_array($images)) && (!empty($images))) {
  113. $filename = $images[0];
  114. }
  115. }
  116. if ($filename) {
  117. $imagePath = $page->path() . '/' . $filename;
  118. if (file_exists($imagePath)) {
  119. $size = getimagesize($imagePath);
  120. $this->webpage->image = new Image();
  121. $this->webpage->image->url = preg_replace('/' . preg_quote($page->urlExtension()) . '$/u', '', $page->url(true)) . '/' . $filename;
  122. $this->webpage->image->id = $this->webpage->url . '#primaryimage';
  123. $this->webpage->image->width = $size[0];
  124. $this->webpage->image->height = $size[1];
  125. $this->webpage->image->caption = $this->webpage->title;
  126. $this->webpage->image->type = $size['mime'];
  127. }
  128. }
  129. if ((isset($header->aura['pagetype'])) && ($header->aura['pagetype'] != '')) {
  130. $this->webpage->type = $header->aura['pagetype'];
  131. }
  132. // Author
  133. if (($this->grav['config']->get('plugins.aura-authors.enabled')) && isset($page->header()->aura['author'])) {
  134. $authors = $this->grav['config']->get('plugins.aura-authors.authors');
  135. $key = array_search($page->header()->aura['author'], array_column($authors, 'label'));
  136. if ($key !== false) {
  137. $author = $authors[$key];
  138. $this->person = new Person();
  139. $this->person->id = $this->org->url . '#person/' . $author['label'];
  140. $this->person->name = $author['name'];
  141. $this->person->description = $author['description'];
  142. // Person SameAs
  143. $sameAs = array();
  144. foreach ($this->otherPresence as $platform) {
  145. $key = 'person-' . $platform;
  146. if (isset($author[$key]) && $author[$key] != '') {
  147. $sameAs[] = $author[$key];
  148. }
  149. }
  150. $key = 'person-twitter-user';
  151. if (isset($author[$key]) && $author[$key] != '') {
  152. $this->person->twitterUser = $author[$key];
  153. $sameAs[] = 'https://twitter.com/' . $author[$key];
  154. }
  155. if (!empty($sameAs)) {
  156. $this->person->sameAs = $sameAs;
  157. }
  158. // Person Image
  159. if ((isset($author['image'])) && (!empty($author['image']))) {
  160. $firstImage = reset($author['image']);
  161. $imagePath = ROOT_DIR . $firstImage['path'];
  162. if (file_exists($imagePath)) {
  163. $size = getimagesize($imagePath);
  164. $this->person->image = new Image();
  165. $this->person->image->url = $this->grav['base_url_absolute'] . '/' . $firstImage['path'];
  166. $this->person->image->id = $this->org->url . '#personimage/' . $author['label'];
  167. $this->person->image->width = $size[0];
  168. $this->person->image->height = $size[1];
  169. $this->person->image->caption = $author['name'];
  170. $this->person->image->type = $size['mime'];
  171. }
  172. }
  173. }
  174. }
  175. }
  176. public function generateOpenGraphMeta() {
  177. $data = array(
  178. 'og:url' => $this->webpage->url,
  179. 'og:type' => $this->webpage->type,
  180. 'og:title' => $this->webpage->title,
  181. );
  182. if ($this->webpage->description) {
  183. $data['og:description'] = $this->webpage->description;
  184. }
  185. if ($this->webpage->image) {
  186. $data['og:image'] = $this->webpage->image->url;
  187. $data['og:image:type'] = $this->webpage->image->type;
  188. $data['og:image:width'] = $this->webpage->image->width;
  189. $data['og:image:height'] = $this->webpage->image->height;
  190. }
  191. if ($this->grav['config']->get('plugins.aura.org-facebook-appid')) {
  192. $data['fb:app_id'] = $this->grav['config']->get('plugins.aura.org-facebook-appid');
  193. }
  194. if ($this->person) {
  195. $data['og:author'] = $this->person->name;
  196. } else {
  197. $data['og:author'] = $this->org->name;
  198. }
  199. foreach ($data as $property => $content) {
  200. $this->webpage->metadata[$property] = array(
  201. 'property' => $property,
  202. 'content' => htmlentities($content),
  203. );
  204. }
  205. }
  206. public function generateTwitterMeta() {
  207. $data = array(
  208. 'twitter:card' => 'summary_large_image',
  209. 'twitter:title' => $this->webpage->title,
  210. );
  211. if ($this->webpage->description) {
  212. $data['twitter:description'] = $this->webpage->description;
  213. }
  214. if ($this->grav['config']->get('plugins.aura.org-twitter-user')) {
  215. $data['twitter:site'] = '@' . $this->grav['config']->get('plugins.aura.org-twitter-user');
  216. }
  217. if ($this->person && $this->person->twitterUser) {
  218. $data['twitter:creator'] = '@' . $this->person->twitterUser;
  219. } else {
  220. if ($this->grav['config']->get('plugins.aura.org-twitter-user')) {
  221. $data['twitter:creator'] = '@' . $this->grav['config']->get('plugins.aura.org-twitter-user');
  222. }
  223. }
  224. if ($this->webpage->image) {
  225. $data['twitter:image'] = $this->webpage->image->url;
  226. }
  227. foreach ($data as $name => $content) {
  228. $this->webpage->metadata[$name] = array(
  229. 'name' => $name,
  230. 'content' => htmlentities($content),
  231. );
  232. }
  233. }
  234. public function generateLinkedInMeta() {
  235. $data = array(
  236. 'article:published_time' => $this->webpage->datePublished,
  237. 'article:modified_time' => $this->webpage->dateModified,
  238. );
  239. if ($this->person) {
  240. $data['article:author'] = $this->person->name;
  241. } else {
  242. $data['article:author'] = $this->org->name;
  243. }
  244. foreach ($data as $property => $content) {
  245. $this->webpage->metadata[$property] = array(
  246. 'property' => $property,
  247. 'content' => htmlentities($content),
  248. );
  249. }
  250. }
  251. public function generateStructuredData() {
  252. $organization = array(
  253. '@type' => 'Organization',
  254. '@id' => $this->org->id,
  255. 'name' => $this->org->name,
  256. 'url' => $this->org->url,
  257. );
  258. $website = array(
  259. '@type' => 'WebSite',
  260. '@id' => $this->website->id,
  261. 'url' => $this->website->url,
  262. 'name' => $this->website->name,
  263. 'publisher' => array(
  264. '@id' => $this->org->id,
  265. ),
  266. );
  267. $webpage = array(
  268. '@type' => 'WebPage',
  269. '@id' => $this->webpage->id,
  270. 'url' => $this->webpage->url,
  271. 'inLanguage' => $this->webpage->language,
  272. 'name' => $this->webpage->title,
  273. 'isPartOf' => array(
  274. '@id' => $this->website->id,
  275. ),
  276. 'datePublished' => $this->webpage->datePublished,
  277. 'dateModified' => $this->webpage->dateModified,
  278. );
  279. // Add Organization sameAs (if defined)
  280. if ($this->org->sameAs) {
  281. $organization['sameAs'] = $this->org->sameAs;
  282. }
  283. // Add logo (if defined)
  284. if ($this->org->logo) {
  285. $organization['logo'] = array(
  286. '@type' => 'ImageObject',
  287. '@id' => $this->org->logo->id,
  288. 'url' => $this->org->logo->url,
  289. 'width' => $this->org->logo->width,
  290. 'height' => $this->org->logo->height,
  291. 'caption' => $this->org->logo->caption,
  292. );
  293. $organization['image'] = array(
  294. '@id' => $this->org->logo->id,
  295. );
  296. }
  297. // Add page description (if defined)
  298. if ($this->webpage->description) {
  299. $webpage['description'] = $this->webpage->description;
  300. }
  301. // Add page image (if defined)
  302. if ($this->webpage->image) {
  303. $webpageImage = array(
  304. '@type' => 'ImageObject',
  305. '@id' => $this->webpage->image->id,
  306. 'url' => $this->webpage->image->url,
  307. 'width' => $this->webpage->image->width,
  308. 'height' => $this->webpage->image->height,
  309. 'caption' => $this->webpage->image->caption,
  310. );
  311. $webpage['primaryImageOfPage'] = array(
  312. '@id' => $this->webpage->image->id,
  313. );
  314. }
  315. // Additional based on page type i.e. article
  316. if ($this->webpage->type == 'article') {
  317. $article = array(
  318. '@type' => 'Article',
  319. '@id' => $this->webpage->url . '#article',
  320. 'isPartOf' => array(
  321. '@id' => $this->webpage->id,
  322. ),
  323. 'headline' => $this->webpage->title,
  324. 'datePublished' => $this->webpage->datePublished,
  325. 'dateModified' => $this->webpage->dateModified,
  326. 'mainEntityOfPage' => array(
  327. '@id' => $this->webpage->id,
  328. ),
  329. 'publisher' => array(
  330. '@id' => $this->org->id,
  331. ),
  332. );
  333. // Add Image
  334. if ($this->webpage->image) {
  335. $article['image'] = array(
  336. '@id' => $this->webpage->image->id,
  337. );
  338. }
  339. // Add Author
  340. if ($this->person) {
  341. // Use Person (if defined)
  342. $person = array(
  343. '@type' => 'Person',
  344. '@id' => $this->person->id,
  345. 'name' => $this->person->name,
  346. );
  347. // Add Person description (if defined)
  348. if ($this->person->description) {
  349. $person['description'] = $this->person->description;
  350. }
  351. // Add Person sameAs (if defined)
  352. if ($this->person->sameAs) {
  353. $person['sameAs'] = $this->person->sameAs;
  354. }
  355. // Add Person image (if defined)
  356. if ($this->person->image) {
  357. $person['image'] = array(
  358. '@type' => 'ImageObject',
  359. '@id' => $this->person->image->id,
  360. 'url' => $this->person->image->url,
  361. 'width' => $this->person->image->width,
  362. 'height' => $this->person->image->height,
  363. 'caption' => $this->person->image->caption,
  364. );
  365. }
  366. $article['author'] = array(
  367. '@id' => $this->person->id,
  368. );
  369. } else {
  370. // Use Organization
  371. $article['author'] = array(
  372. '@id' => $this->org->id,
  373. );
  374. }
  375. }
  376. // Build the empty structured data block
  377. $data = array(
  378. '@context' => 'https://schema.org',
  379. '@graph' => array(),
  380. );
  381. // Add the elements in order
  382. $data['@graph'][] = $organization;
  383. $data['@graph'][] = $website;
  384. if (isset($webpageImage)) {
  385. $data['@graph'][] = $webpageImage;
  386. }
  387. $data['@graph'][] = $webpage;
  388. if (isset($article)) {
  389. $data['@graph'][] = $article;
  390. }
  391. if (isset($person)) {
  392. $data['@graph'][] = $person;
  393. }
  394. return json_encode($data, JSON_UNESCAPED_SLASHES);
  395. }
  396. }