class-wp-unittest-factory-for-thing.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. /**
  3. * An abstract class that serves as a basis for all WordPress object-type factory classes.
  4. */
  5. abstract class WP_UnitTest_Factory_For_Thing {
  6. public $default_generation_definitions;
  7. public $factory;
  8. /**
  9. * Creates a new factory, which will create objects of a specific Thing
  10. *
  11. * @param object $factory Global factory that can be used to create other objects on the system
  12. * @param array $default_generation_definitions Defines what default values should the properties of the object have. The default values
  13. * can be generators -- an object with next() method. There are some default generators: {@link WP_UnitTest_Generator_Sequence},
  14. * {@link WP_UnitTest_Generator_Locale_Name}, {@link WP_UnitTest_Factory_Callback_After_Create}.
  15. */
  16. public function __construct( $factory, $default_generation_definitions = array() ) {
  17. $this->factory = $factory;
  18. $this->default_generation_definitions = $default_generation_definitions;
  19. }
  20. /**
  21. * Creates an object.
  22. *
  23. * @param array $args The arguments.
  24. *
  25. * @return mixed The result. Can be anything.
  26. */
  27. abstract public function create_object( $args );
  28. /**
  29. * Updates an existing object.
  30. *
  31. * @param int $object The object ID.
  32. * @param array $fields The values to update.
  33. *
  34. * @return mixed The result. Can be anything.
  35. */
  36. abstract public function update_object( $object, $fields );
  37. /**
  38. * Creates an object.
  39. *
  40. * @param array $args Optional. The arguments for the object to create. Default is empty array.
  41. * @param null $generation_definitions Optional. The default values for the object. Default is null.
  42. *
  43. * @return mixed The result. Can be anything.
  44. */
  45. public function create( $args = array(), $generation_definitions = null ) {
  46. if ( is_null( $generation_definitions ) ) {
  47. $generation_definitions = $this->default_generation_definitions;
  48. }
  49. $generated_args = $this->generate_args( $args, $generation_definitions, $callbacks );
  50. $created = $this->create_object( $generated_args );
  51. if ( ! $created || is_wp_error( $created ) ) {
  52. return $created;
  53. }
  54. if ( $callbacks ) {
  55. $updated_fields = $this->apply_callbacks( $callbacks, $created );
  56. $save_result = $this->update_object( $created, $updated_fields );
  57. if ( ! $save_result || is_wp_error( $save_result ) ) {
  58. return $save_result;
  59. }
  60. }
  61. return $created;
  62. }
  63. /**
  64. * Creates an object and returns its object.
  65. *
  66. * @param array $args Optional. The arguments for the object to create. Default is empty array.
  67. * @param null $generation_definitions Optional. The default values for the object. Default is null.
  68. *
  69. * @return mixed The created object. Can be anything.
  70. */
  71. public function create_and_get( $args = array(), $generation_definitions = null ) {
  72. $object_id = $this->create( $args, $generation_definitions );
  73. if ( is_wp_error( $object_id ) ) {
  74. return $object_id;
  75. }
  76. return $this->get_object_by_id( $object_id );
  77. }
  78. /**
  79. * Retrieves an object by ID.
  80. *
  81. * @param int $object_id The object ID.
  82. *
  83. * @return mixed The object. Can be anything.
  84. */
  85. abstract public function get_object_by_id( $object_id );
  86. /**
  87. * Creates multiple objects.
  88. *
  89. * @param int $count Amount of objects to create.
  90. * @param array $args Optional. The arguments for the object to create. Default is empty array.
  91. * @param null $generation_definitions Optional. The default values for the object. Default is null.
  92. *
  93. * @return array
  94. */
  95. public function create_many( $count, $args = array(), $generation_definitions = null ) {
  96. $results = array();
  97. for ( $i = 0; $i < $count; $i++ ) {
  98. $results[] = $this->create( $args, $generation_definitions );
  99. }
  100. return $results;
  101. }
  102. /**
  103. * Combines the given arguments with the generation_definitions (defaults) and applies
  104. * possibly set callbacks on it.
  105. *
  106. * @param array $args Optional. The arguments to combine with defaults. Default is empty array.
  107. * @param array|null $generation_definitions Optional. The defaults. Default is null.
  108. * @param array|null $callbacks Optional. Array with callbacks to apply on the fields. Default is null.
  109. *
  110. * @return array|WP_Error Combined array on success. WP_Error when default value is incorrent.
  111. */
  112. public function generate_args( $args = array(), $generation_definitions = null, &$callbacks = null ) {
  113. $callbacks = array();
  114. if ( is_null( $generation_definitions ) ) {
  115. $generation_definitions = $this->default_generation_definitions;
  116. }
  117. // Use the same incrementor for all fields belonging to this object.
  118. $gen = new WP_UnitTest_Generator_Sequence();
  119. // Add leading zeros to make sure MySQL sorting works as expected.
  120. $incr = zeroise( $gen->get_incr(), 7 );
  121. foreach ( array_keys( $generation_definitions ) as $field_name ) {
  122. if ( ! isset( $args[ $field_name ] ) ) {
  123. $generator = $generation_definitions[ $field_name ];
  124. if ( is_scalar( $generator ) ) {
  125. $args[ $field_name ] = $generator;
  126. } elseif ( is_object( $generator ) && method_exists( $generator, 'call' ) ) {
  127. $callbacks[ $field_name ] = $generator;
  128. } elseif ( is_object( $generator ) ) {
  129. $args[ $field_name ] = sprintf( $generator->get_template_string(), $incr );
  130. } else {
  131. return new WP_Error( 'invalid_argument', 'Factory default value should be either a scalar or an generator object.' );
  132. }
  133. }
  134. }
  135. return $args;
  136. }
  137. /**
  138. * Applies the callbacks on the created object.
  139. *
  140. * @param WP_UnitTest_Factory_Callback_After_Create[] $callbacks Array with callback functions.
  141. * @param mixed $created The object to apply callbacks for.
  142. *
  143. * @return array The altered fields.
  144. */
  145. public function apply_callbacks( $callbacks, $created ) {
  146. $updated_fields = array();
  147. foreach ( $callbacks as $field_name => $generator ) {
  148. $updated_fields[ $field_name ] = $generator->call( $created );
  149. }
  150. return $updated_fields;
  151. }
  152. /**
  153. * Instantiates a callback objects for the given function name.
  154. *
  155. * @param string $function The callback function.
  156. *
  157. * @return WP_UnitTest_Factory_Callback_After_Create
  158. */
  159. public function callback( $function ) {
  160. return new WP_UnitTest_Factory_Callback_After_Create( $function );
  161. }
  162. /**
  163. * Adds slashes to the given value.
  164. *
  165. * @param array|object|string|mixed $value The value to add slashes to.
  166. *
  167. * @return array|string The value with the possibly applied slashes.
  168. */
  169. public function addslashes_deep( $value ) {
  170. if ( is_array( $value ) ) {
  171. $value = array_map( array( $this, 'addslashes_deep' ), $value );
  172. } elseif ( is_object( $value ) ) {
  173. $vars = get_object_vars( $value );
  174. foreach ( $vars as $key => $data ) {
  175. $value->{$key} = $this->addslashes_deep( $data );
  176. }
  177. } elseif ( is_string( $value ) ) {
  178. $value = addslashes( $value );
  179. }
  180. return $value;
  181. }
  182. }