jsonLD.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. <?php
  2. namespace app\modules\ldjson;
  3. use Yii;
  4. use yii\base\BaseObject;
  5. use yii\helpers\Html;
  6. use yii\helpers\Url;
  7. use Masterminds\HTML5;
  8. class jsonLD extends BaseObject{
  9. public static $author=array();
  10. public static $publisher=array();
  11. public static $ld=array(
  12. "@context"=>"https://schema.org",
  13. "@type"=>"NewsArticle"
  14. );
  15. public static $wp = array(
  16. "@context"=>"https://schema.org",
  17. "@type"=>"WebPage"
  18. );
  19. public static $person = array(
  20. );
  21. public static $identifier = array(
  22. "@type"=>"PropertyValue",
  23. "propertyID"=>"WebPage",
  24. );
  25. public static $faq = array(
  26. "@context"=>"https://schema.org",
  27. "@type"=>"FAQPage",
  28. "mainEntity" => []
  29. );
  30. public static $about=array();
  31. public static $breadcrumb=array();
  32. public static $init = false;
  33. public static $ffaq = false;
  34. public function jsonLD(){
  35. }
  36. public function init(){
  37. self::$init = false;
  38. }
  39. public static function addAmicORG(){
  40. self::$init = true;
  41. self::$publisher=array(
  42. "@type"=>"NewsMediaOrganization",
  43. "name"=> Yii::$app->params['orgname'],
  44. "legalName"=>"Информационное агентство Амител",
  45. "masthead"=>"https://www.amic.ru/about",
  46. "actionableFeedbackPolicy"=>"https://www.amic.ru/feedback/",
  47. "logo"=>array(
  48. "@type"=>"ImageObject",
  49. "url"=>Yii::$app->urlManager->hostInfo.'/img/logo-google.png'
  50. ),
  51. // "description"=>'Новости Барнаула и Алтайского края, новости мира и России самое интересное. Новостное агенство ООО "Амител"',
  52. "email"=>"news@amic.ru",
  53. "telephone"=>"(7-385-2) 27-18-18",
  54. "url"=>Yii::$app->urlManager->hostInfo
  55. );
  56. }
  57. //sameAs
  58. public static function story($name){
  59. self::$about[] = $name;
  60. }
  61. public static function author($name, $type = true){
  62. self::$author["name"] = $name;
  63. if( $type ){
  64. self::$author["@type"] = "Person";
  65. }else{
  66. self::$author["@type"] = "Organization";
  67. }
  68. }
  69. public static function publisher($name){
  70. $publisher["name"] = $name;
  71. }
  72. public static function addBreadcrumb( $lavel, $url, $name ){
  73. $lb = array( 'position'=>$lavel, '@id'=>$url, 'name'=>$name );
  74. self::$breadcrumb[] = $lb;
  75. }
  76. //_big_640.jpg _size1
  77. public static function news( $title, $description, $image, $dtpub, $url, $uid='', $text='', $alt_title='' ){
  78. self::$wp["@id"] = $url;
  79. self::$identifier['value'] = $uid;
  80. $a = array(
  81. "@type"=>"Person",
  82. "headline"=>$title,
  83. "url"=>Yii::$app->urlManager->hostInfo.$url,
  84. "mainEntityOfPage"=>$url,
  85. "datePublished"=>date("c", strtotime($dtpub)),
  86. "description"=>$description,
  87. "@id"=>Yii::$app->urlManager->hostInfo.$url,
  88. "image"=>$image,
  89. "mainEntityOfPage"=>$url //self::$wp
  90. );
  91. //alternativeHeadline
  92. //dateModified
  93. //dateCreate
  94. if( $uid ){
  95. $a['identifier'] = self::$identifier;
  96. }
  97. if( $text ){
  98. $text = trim($text);
  99. $text = str_replace(["\n","\r","&nbsp;"],'',$text);
  100. $text = str_replace(["&nbsp;"],' ',$text);
  101. $a['articleBody'] = strip_tags( $text );
  102. }
  103. if( $alt_title ){
  104. $a['alternativeHeadline'] = htmlspecialchars( strip_tags($alt_title) );
  105. }
  106. self::$ld = self::$ld + $a;
  107. }
  108. public static function addfaq( $text, $headline ){
  109. self::$faq['headline'] = $headline;
  110. $html5 = new HTML5();
  111. $dom = $html5->loadHTML($text);
  112. $el = $dom->getElementsByTagName('div');
  113. $divs = iterator_to_array($el);
  114. foreach ($divs as $div) {
  115. if($div->getAttribute('class') == 'Card-fon'){
  116. $flag = 0;
  117. $Question = '';
  118. $Answer = '';
  119. $card = $div->getElementsByTagName('h2');
  120. $divcard = iterator_to_array($card);
  121. foreach ($divcard as $cdiv) {
  122. if($cdiv->getAttribute('class') == 'Card-vnutr'){
  123. if( strstr( $cdiv->textContent, '?') !== false ){
  124. $Question = $cdiv->textContent;
  125. $flag++;
  126. }
  127. }
  128. }
  129. if( $flag == 0 ){
  130. $card = $div->getElementsByTagName('div');
  131. $divcard = iterator_to_array($card);
  132. foreach ($divcard as $cdiv) {
  133. if($cdiv->getAttribute('class') == 'Card-vnutr'){
  134. if( strstr( $cdiv->textContent, '?') !== false ){
  135. $Question = $cdiv->textContent;
  136. $flag++;
  137. }
  138. }
  139. }
  140. }
  141. if( $flag ){
  142. $card = $div->getElementsByTagName('div');
  143. $divcard = iterator_to_array($card);
  144. $Answer = '';
  145. foreach ($divcard as $cdiv) {
  146. if($cdiv->getAttribute('class') == 'Card-text'){
  147. $Answer .= $cdiv->textContent;
  148. $flag++;
  149. }
  150. }
  151. }
  152. if( $flag > 1 ){
  153. $a = [
  154. "@type" => "Question",
  155. "name" => $Question,
  156. "acceptedAnswer" => [
  157. "@type" => "Answer",
  158. "text"=>$Answer
  159. ]
  160. ];
  161. self::$faq['mainEntity'][] = $a;
  162. self::$ffaq = true;
  163. }
  164. }
  165. }
  166. }
  167. public static function person( $title, $description, $jobTitle, $image, $url, $birthDate = '' ){
  168. $text = strip_tags(trim($description));
  169. $text = str_replace(["\n","\r","&nbsp;"],'',$text);
  170. $text = str_replace(["&nbsp;"],' ',$text);
  171. $a = array(
  172. "name"=>$title,
  173. "url"=>$url,
  174. "description"=>$text,
  175. "image"=>$image,
  176. "jobTitle"=>htmlspecialchars($jobTitle)
  177. );
  178. if( $birthDate && $birthDate != '1970-01-01' && strtotime($birthDate) > 10){
  179. $a['birthDate'] = date("c", strtotime($birthDate));
  180. }
  181. self::$person = self::$person + $a;
  182. }
  183. public static function showtest(){
  184. $a = self::$ld;
  185. if( self::$author ) $a["author"] = self::$author;
  186. $a["publisher"] = self::$publisher;
  187. if( count( self::$person ) ){
  188. $a['@type'] = "Person";
  189. $a += self::$person;
  190. }
  191. if( count( self::$about ) ){
  192. $labout = array();
  193. foreach( self::$about as $name ){
  194. $labout[] = array( "@type" => "InformAction", "name" => $name );
  195. }
  196. $a["about"] = $labout;
  197. }
  198. if( count( self::$breadcrumb ) ){
  199. $labout = array();
  200. foreach( self::$breadcrumb as $item ){
  201. $labout[] = array( "@type" => "ListItem", 'position' => $item['position'], 'item' => array( "@id" => $item['@id'], "name" => $item['name'] ) );
  202. }
  203. $aa = array(
  204. "@type" => "BreadcrumbList",
  205. "itemListElement" => $labout
  206. );
  207. //$a = $a + $aa;
  208. $a = array_diff_key( $a, array( '@context' => 'https://schema.org' ) );
  209. $b = array("@context" => 'https://schema.org', "@graph" => array( $a, $aa ));
  210. }else{
  211. $a = array_diff_key( $a, array( '@context' => 'https://schema.org' ) );
  212. $b = array("@context" => 'https://schema.org', "@graph" => array( $a ));
  213. }
  214. echo "<!-- debug\n".self::_format_json(json_encode( $b, JSON_UNESCAPED_UNICODE ), false)." \n-->\n";
  215. if( self::$ffaq ){
  216. $aa = array(
  217. "@context" => 'https://schema.org'
  218. );
  219. echo "<!-- debug\n".self::_format_json(json_encode( $aa+self::$faq, JSON_UNESCAPED_UNICODE ), false)." \n-->\n";
  220. }
  221. }
  222. public static function show(){
  223. $a = self::$ld;
  224. $a["author"] = self::$author;
  225. $a["publisher"] = self::$publisher;
  226. echo json_encode( $a );
  227. }
  228. public static function get(){
  229. if( self::$init == false ) return '';
  230. $a = self::$ld;
  231. if( count( self::$person ) ){
  232. $a['@type'] = "Person";
  233. $a += self::$person;
  234. }else{
  235. $a["author"] = self::$author;
  236. $a["publisher"] = self::$publisher;
  237. }
  238. if( count( self::$about ) ){
  239. $labout = array();
  240. foreach( self::$about as $name ){
  241. $labout[] = array( "@type" => "InformAction", "name" => $name );
  242. }
  243. $a["about"] = $labout;
  244. }
  245. /*
  246. $a = $this->ld;
  247. $a["author"] = $this->author;
  248. $a["publisher"] = $this->publisher;
  249. if( count( $this->about ) ){
  250. $labout = array();
  251. foreach( $this->about as $name ){
  252. $labout[] = array( "@type" => "Event", "name" => $name );
  253. }
  254. $a["about"] = $labout;
  255. }
  256. */
  257. if( count( self::$breadcrumb ) ){
  258. $labout = array();
  259. foreach( self::$breadcrumb as $item ){
  260. $labout[] = array( "@type" => "ListItem", 'position' => $item['position'], 'item' => array( "@id" => $item['@id'], "name" => $item['name'] ) );
  261. }
  262. $aa = array(
  263. "@context" => 'https://schema.org',
  264. "@type" => "BreadcrumbList",
  265. "itemListElement" => $labout
  266. );
  267. //$a = $a + $aa;
  268. // $a = array_diff_key( $a, array( '@context' => 'https://schema.org' ) );
  269. // $b = array( "@graph" => array( $aa, $a ));
  270. }
  271. $r = '<script type="application/ld+json">'.json_encode( $a, JSON_UNESCAPED_UNICODE ).'</script>'."\n";
  272. $r .= ( isset($aa) )?'<script type="application/ld+json">'.json_encode( $aa, JSON_UNESCAPED_UNICODE ).'</script>'."\n":'';
  273. if( self::$ffaq ){
  274. $aaa = array(
  275. "@context" => 'https://schema.org'
  276. );
  277. $r .='<script type="application/ld+json">'.json_encode( $aaa+self::$faq, JSON_UNESCAPED_UNICODE ).'</script>'."\n";
  278. }
  279. return $r;
  280. }
  281. public static function _format_json($json, $html = false) {
  282. $tabcount = 0;
  283. $result = '';
  284. $inquote = false;
  285. $ignorenext = false;
  286. if ($html) {
  287. $tab = "&nbsp;&nbsp;&nbsp;&nbsp;";
  288. $newline = "<br/>";
  289. } else {
  290. $tab = "\t";
  291. $newline = "\n";
  292. }
  293. for($i = 0; $i < strlen($json); $i++) {
  294. $char = $json[$i];
  295. if ($ignorenext) {
  296. $result .= $char;
  297. $ignorenext = false;
  298. } else {
  299. switch($char) {
  300. case '[':
  301. case '{':
  302. $tabcount++;
  303. $result .= $char . $newline . str_repeat($tab, $tabcount);
  304. break;
  305. case ']':
  306. case '}':
  307. $tabcount--;
  308. $result = trim($result) . $newline . str_repeat($tab, $tabcount) . $char;
  309. break;
  310. case ',':
  311. $result .= $char . $newline . str_repeat($tab, $tabcount);
  312. break;
  313. case ':':
  314. $result .= $char . " ";
  315. break;
  316. case '"':
  317. $inquote = !$inquote;
  318. $result .= $char;
  319. break;
  320. case '\\':
  321. if ($inquote) $ignorenext = true;
  322. $result .= $char;
  323. break;
  324. default:
  325. $result .= $char;
  326. }
  327. }
  328. }
  329. return str_replace(': //','://',str_replace('\/','/',$result));
  330. }
  331. public static function addBreadcrumbList()
  332. {
  333. $view = Yii::$app->getView();
  334. $breadcrumbList = [];
  335. if (isset($view->params['breadcrumbs'])) {
  336. $position = 1;
  337. foreach ($view->params['breadcrumbs'] as $breadcrumb) {
  338. if (is_array($breadcrumb)) {
  339. $breadcrumbList[] = (object)[
  340. "@type" => "http://schema.org/ListItem",
  341. "http://schema.org/position" => $position,
  342. "http://schema.org/item" => (object)[
  343. "@id" => Url::to($breadcrumb['url'], true),
  344. "http://schema.org/name" => $breadcrumb['label'],
  345. ]
  346. ];
  347. } else {
  348. // Is it ok to omit URL here or not? Google is not clear on that:
  349. // http://stackoverflow.com/questions/33688608/how-to-markup-the-last-non-linking-item-in-breadcrumbs-list-using-json-ld
  350. $breadcrumbList[] = (object)[
  351. "@type" => "http://schema.org/ListItem",
  352. "http://schema.org/position" => $position,
  353. "http://schema.org/item" => (object)[
  354. "http://schema.org/name" => $breadcrumb,
  355. ]
  356. ];
  357. }
  358. $position++;
  359. }
  360. }
  361. $doc = (object)[
  362. "@type" => "http://schema.org/BreadcrumbList",
  363. "http://schema.org/itemListElement" => $breadcrumbList
  364. ];
  365. JsonLDHelper::add($doc);
  366. }
  367. }