/DuckDuckGo/ZeroClickInfo.php

https://github.com/duckduckgo/php5-duckduckgo · PHP · 211 lines · 97 code · 33 blank · 81 comment · 11 complexity · f531a7bd678d2d5592c4c573ac7a901a MD5 · raw file

  1. <?php
  2. /**
  3. * @file DuckDuckGo/ZeroClickInfo.php
  4. * This file contains the ZeroClickInfo result class.
  5. */
  6. namespace DuckDuckGo;
  7. /**
  8. * The class holding the result of a ZeroClickInfo query.
  9. */
  10. class ZeroClickInfo extends APIResult
  11. {
  12. /* Constants */
  13. /**
  14. * 'Enumeration' for ZeroClickInfo result types.
  15. */
  16. const TYPE_NONE = 0;
  17. const TYPE_ARTICLE = 1;
  18. const TYPE_CATEGORY = 2;
  19. const TYPE_DISAMBIGUATION = 3;
  20. const TYPE_EXCLUSIVE = 4;
  21. const TYPE_NAME = 5;
  22. /* Mappings */
  23. /**
  24. * Mappings from the Type field of the result to the enumeration above.
  25. */
  26. protected static $resultTypeMapping = array(
  27. 'A' => self::TYPE_ARTICLE,
  28. 'C' => self::TYPE_CATEGORY,
  29. 'D' => self::TYPE_DISAMBIGUATION,
  30. 'E' => self::TYPE_EXCLUSIVE,
  31. 'N' => self::TYPE_NAME,
  32. );
  33. /**
  34. * Direct API field --> member mappings.
  35. * @see APIResult
  36. */
  37. protected static $directMappings = array(
  38. 'Abstract' => 'summary',
  39. 'AbstractText' => 'textSummary',
  40. 'AbstractSource' => 'summarySource',
  41. 'AbstractURL' => 'summarySourceURL',
  42. 'Image' => 'imageURL',
  43. 'Heading' => 'heading',
  44. 'Answer' => 'answer',
  45. 'AnswerType' => 'answerType',
  46. 'Definition' => 'definition',
  47. 'DefinitionSource' => 'definitionSource',
  48. 'DefinitionURL' => 'definitionSourceURL',
  49. );
  50. /* Query result fields. */
  51. /**
  52. * Title of the result.
  53. */
  54. public $heading;
  55. /**
  56. * Summary of the topic.
  57. */
  58. public $summary;
  59. /**
  60. * Plain-text summary of the topic. ]
  61. */
  62. public $textSummary;
  63. /**
  64. * Source of the summary.
  65. */
  66. public $summarySource;
  67. /**
  68. * URL of the summary source.
  69. */
  70. public $summarySourceURL;
  71. /**
  72. * Image URL to a possibly relevant image.
  73. */
  74. public $imageURL;
  75. /**
  76. * Instant answer for the query, if applicable.
  77. */
  78. public $answer;
  79. /**
  80. * Type of instant answer (calc, color, phone, pw, regexp...)
  81. */
  82. public $answerType;
  83. /**
  84. * Dictionary definition of query, if applicable.
  85. */
  86. public $definition;
  87. /**
  88. * Source of dictionary definition.
  89. */
  90. public $definitionSource;
  91. /**
  92. * Source URL of the dictionary definition.
  93. */
  94. public $definitionSourceURL;
  95. /**
  96. * An array containing the related topics.
  97. * The keys in the first level of the array are the category names of the topics,
  98. * the values are arrays containing all the topics under that category.
  99. * A topic is a simple stdClass object containing the following members:
  100. * - description, a description of the related subject.
  101. * - URL, a URL to the ZeroClickInfo of that subject.
  102. * - iconURL, a URL to an icon for that subject, if applicable.
  103. */
  104. public $relatedTopics;
  105. /**
  106. * An array of external links (results).
  107. * For the result format, see the topic format above.
  108. */
  109. public $results;
  110. /**
  111. * Response type, one of the TYPE_ constants in this class.
  112. * To test for a certain type, use for example $result->type == DuckDuckGo\\ZeroClickInfo::TYPE_ARTICLE
  113. */
  114. public $type;
  115. /* Constructors and miscellaneous functions. */
  116. /**
  117. * Constructor. Not for public use, only to be used by the API object.
  118. */
  119. public function __construct($data)
  120. {
  121. if(!$data) {
  122. throw new Exception('Unable to parse result data.');
  123. }
  124. /* Process direct mappings first. */
  125. foreach(self::$directMappings as $apiKey => $memberName) {
  126. if(isset($data[$apiKey])) {
  127. $this->$memberName = $data[$apiKey];
  128. } else {
  129. $this->$memberName = NULL;
  130. }
  131. }
  132. /* Now process special API fields. */
  133. /* The ZeroClickInfo type. */
  134. if(isset($data['Type']) && isset(self::$resultTypeMapping[$data['Type']])) {
  135. $this->type = self::$resultTypeMapping[$data['Type']];
  136. } else {
  137. $this->type = self::TYPE_NONE;
  138. }
  139. /* Related URLs. */
  140. if(isset($data['Results'])) {
  141. $this->results = array();
  142. foreach($data['Results'] as $apiResult) {
  143. $result = new \stdClass();
  144. $result->description = $apiResult['Text'];
  145. $result->URL = $apiResult['FirstURL'];
  146. $result->iconURL = $apiResult['Icon']['URL'];
  147. $this->results[] = $result;
  148. }
  149. }
  150. /* Related internal topics. */
  151. if(isset($data['RelatedTopics'])) {
  152. $this->relatedTopics = array();
  153. foreach($data['RelatedTopics'] as $subject) {
  154. if(isset($subject['Name'])) {
  155. /* This is a seperate category */
  156. $this->relatedTopics[$subject['Name']] = array();
  157. foreach($subject['Topics'] as $apiRelatedTopic) {
  158. $relatedTopic = new \stdClass();
  159. $relatedTopic->description = $apiRelatedTopic['Text'];
  160. $relatedTopic->URL = $apiRelatedTopic['FirstURL'];
  161. $relatedTopic->iconURL = $apiRelatedTopic['Icon']['URL'];
  162. $this->relatedTopics[$subject['Name']][] = $relatedTopic;
  163. }
  164. } else {
  165. /* This is a 'global' topic, put it in the general category. */
  166. $relatedTopic = new \stdClass();
  167. $relatedTopic->description = $subject['Text'];
  168. $relatedTopic->URL = $subject['FirstURL'];
  169. $relatedTopic->iconURL = $subject['Icon']['URL'];
  170. if(!isset($this->relatedTopics['General'])) {
  171. $this->relatedTopics['General'] = array();
  172. }
  173. $this->relatedTopics['General'][] = $relatedTopic;
  174. }
  175. }
  176. }
  177. }
  178. }