You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
3.8 KiB

  1. <?php
  2. namespace Percolator\Formats;
  3. class Mf2 {
  4. public static function parse($mf2) {
  5. $data = [
  6. 'type' => 'entry',
  7. 'author' => [
  8. 'type' => 'card',
  9. 'name' => null,
  10. 'url' => null,
  11. 'photo' => null
  12. ]
  13. ];
  14. if($item = $mf2['items'][0]) {
  15. if(in_array('h-entry', $item['type'])) {
  16. // Single plaintext values
  17. $properties = ['url','published','summary','rsvp'];
  18. foreach($properties as $p) {
  19. if($v = self::getPlaintext($item, $p))
  20. $data[$p] = $v;
  21. }
  22. // Always arrays
  23. $properties = ['photo','video','syndication','in-reply-to','like-of','repost-of'];
  24. foreach($properties as $p) {
  25. if(array_key_exists($p, $item['properties']))
  26. $data[$p] = $item['properties'][$p];
  27. }
  28. // Determine if the name is distinct from the content
  29. $name = self::getPlaintext($item, 'name');
  30. $content = null;
  31. $textContent = null;
  32. $htmlContent = null;
  33. if(array_key_exists('content', $item['properties'])) {
  34. $content = $item['properties']['content'][0];
  35. if(is_string($content)) {
  36. $textContent = $content;
  37. } elseif(!is_string($content) && is_array($content) && array_key_exists('value', $content)) {
  38. if(array_key_exists('html', $content)) {
  39. $textContent = strip_tags($content['html']);
  40. $htmlContent = $content['html'];
  41. } else {
  42. $textContent = $content['value'];
  43. }
  44. }
  45. // Trim ellipses from the name
  46. $name = preg_replace('/ ?(\.\.\.|…)$/', '', $name);
  47. // Check if the name is a prefix of the content
  48. if(strpos($textContent, $name) === 0) {
  49. $name = null;
  50. }
  51. }
  52. if($name) {
  53. $data['name'] = $name;
  54. }
  55. if($content) {
  56. $data['content'] = [
  57. 'text' => $textContent
  58. ];
  59. if($textContent != $htmlContent) {
  60. $data['content']['html'] = $htmlContent;
  61. }
  62. }
  63. return $data;
  64. }
  65. }
  66. return false;
  67. }
  68. private static function responseDisplayText($name, $summary, $content) {
  69. // Build a fake h-entry to pass to the comments parser
  70. $input = [
  71. 'type' => ['h-entry'],
  72. 'properties' => [
  73. 'name' => [trim($name)],
  74. 'summary' => [trim($summary)],
  75. 'content' => [trim($content)]
  76. ]
  77. ];
  78. if(!trim($name))
  79. unset($input['properties']['name']);
  80. if(!trim($summary))
  81. unset($input['properties']['summary']);
  82. $result = \IndieWeb\comments\parse($input, false, 1024, 4);
  83. return [
  84. 'name' => trim($result['name']),
  85. 'content' => $result['text']
  86. ];
  87. }
  88. private static function hasNumericKeys(array $arr) {
  89. foreach($arr as $key=>$val)
  90. if (is_numeric($key))
  91. return true;
  92. return false;
  93. }
  94. private static function isMicroformat($mf) {
  95. return is_array($mf)
  96. and !self::hasNumericKeys($mf)
  97. and !empty($mf['type'])
  98. and isset($mf['properties']);
  99. }
  100. // Given an array of microformats properties and a key name, return the plaintext value
  101. // at that property
  102. // e.g.
  103. // {"properties":{"published":["foo"]}} results in "foo"
  104. private static function getPlaintext($mf2, $k, $fallback=null) {
  105. if(!empty($mf2['properties'][$k]) and is_array($mf2['properties'][$k])) {
  106. // $mf2['properties'][$v] will always be an array since the input was from the mf2 parser
  107. $value = $mf2['properties'][$k][0];
  108. if(is_string($value)) {
  109. return $value;
  110. } elseif(self::isMicroformat($value) && array_key_exists('value', $value)) {
  111. return $value['value'];
  112. }
  113. }
  114. return $fallback;
  115. }
  116. }