Metadata.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <?php
  2. namespace YahnisElsts\PluginUpdateChecker\v5p1;
  3. use LogicException;
  4. use stdClass;
  5. use WP_Error;
  6. if ( !class_exists(Metadata::class, false) ):
  7. /**
  8. * A base container for holding information about updates and plugin metadata.
  9. *
  10. * @author Janis Elsts
  11. * @copyright 2016
  12. * @access public
  13. */
  14. abstract class Metadata {
  15. /**
  16. * Create an instance of this class from a JSON document.
  17. *
  18. * @abstract
  19. * @param string $json
  20. * @return self
  21. */
  22. public static function fromJson($json) {
  23. throw new LogicException('The ' . __METHOD__ . ' method must be implemented by subclasses');
  24. }
  25. /**
  26. * @param string $json
  27. * @param self $target
  28. * @return bool
  29. */
  30. protected static function createFromJson($json, $target) {
  31. /** @var \StdClass $apiResponse */
  32. $apiResponse = json_decode($json);
  33. if ( empty($apiResponse) || !is_object($apiResponse) ){
  34. $errorMessage = "Failed to parse update metadata. Try validating your .json file with https://jsonlint.com/";
  35. do_action('puc_api_error', new WP_Error('puc-invalid-json', $errorMessage));
  36. //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- For plugin developers.
  37. trigger_error(esc_html($errorMessage), E_USER_NOTICE);
  38. return false;
  39. }
  40. $valid = $target->validateMetadata($apiResponse);
  41. if ( is_wp_error($valid) ){
  42. do_action('puc_api_error', $valid);
  43. //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- For plugin developers.
  44. trigger_error(esc_html($valid->get_error_message()), E_USER_NOTICE);
  45. return false;
  46. }
  47. foreach(get_object_vars($apiResponse) as $key => $value){
  48. $target->$key = $value;
  49. }
  50. return true;
  51. }
  52. /**
  53. * No validation by default! Subclasses should check that the required fields are present.
  54. *
  55. * @param \StdClass $apiResponse
  56. * @return bool|\WP_Error
  57. */
  58. protected function validateMetadata($apiResponse) {
  59. return true;
  60. }
  61. /**
  62. * Create a new instance by copying the necessary fields from another object.
  63. *
  64. * @abstract
  65. * @param \StdClass|self $object The source object.
  66. * @return self The new copy.
  67. */
  68. public static function fromObject($object) {
  69. throw new LogicException('The ' . __METHOD__ . ' method must be implemented by subclasses');
  70. }
  71. /**
  72. * Create an instance of StdClass that can later be converted back to an
  73. * update or info container. Useful for serialization and caching, as it
  74. * avoids the "incomplete object" problem if the cached value is loaded
  75. * before this class.
  76. *
  77. * @return \StdClass
  78. */
  79. public function toStdClass() {
  80. $object = new stdClass();
  81. $this->copyFields($this, $object);
  82. return $object;
  83. }
  84. /**
  85. * Transform the metadata into the format used by WordPress core.
  86. *
  87. * @return object
  88. */
  89. abstract public function toWpFormat();
  90. /**
  91. * Copy known fields from one object to another.
  92. *
  93. * @param \StdClass|self $from
  94. * @param \StdClass|self $to
  95. */
  96. protected function copyFields($from, $to) {
  97. $fields = $this->getFieldNames();
  98. if ( property_exists($from, 'slug') && !empty($from->slug) ) {
  99. //Let plugins add extra fields without having to create subclasses.
  100. $fields = apply_filters($this->getPrefixedFilter('retain_fields') . '-' . $from->slug, $fields);
  101. }
  102. foreach ($fields as $field) {
  103. if ( property_exists($from, $field) ) {
  104. $to->$field = $from->$field;
  105. }
  106. }
  107. }
  108. /**
  109. * @return string[]
  110. */
  111. protected function getFieldNames() {
  112. return array();
  113. }
  114. /**
  115. * @param string $tag
  116. * @return string
  117. */
  118. protected function getPrefixedFilter($tag) {
  119. return 'puc_' . $tag;
  120. }
  121. }
  122. endif;