@@ -12,295 +12,295 @@ |
||
| 12 | 12 | |
| 13 | 13 | class Schema |
| 14 | 14 | { |
| 15 | - /** |
|
| 16 | - * @var array |
|
| 17 | - */ |
|
| 18 | - protected $args; |
|
| 15 | + /** |
|
| 16 | + * @var array |
|
| 17 | + */ |
|
| 18 | + protected $args; |
|
| 19 | 19 | |
| 20 | - /** |
|
| 21 | - * @var array |
|
| 22 | - */ |
|
| 23 | - protected $ratingCounts; |
|
| 20 | + /** |
|
| 21 | + * @var array |
|
| 22 | + */ |
|
| 23 | + protected $ratingCounts; |
|
| 24 | 24 | |
| 25 | - /** |
|
| 26 | - * @return array |
|
| 27 | - */ |
|
| 28 | - public function build(array $args = []) |
|
| 29 | - { |
|
| 30 | - $this->args = $args; |
|
| 31 | - $schema = $this->buildSummary($args); |
|
| 32 | - $reviews = []; |
|
| 33 | - foreach (glsr(ReviewManager::class)->get($this->args) as $review) { |
|
| 34 | - // Only include critic reviews that have been directly produced by your site, not reviews from third-party sites or syndicated reviews. |
|
| 35 | - // @see https://developers.google.com/search/docs/data-types/review |
|
| 36 | - if ('local' != $review->review_type) { |
|
| 37 | - continue; |
|
| 38 | - } |
|
| 39 | - $reviews[] = $this->buildReview($review); |
|
| 40 | - } |
|
| 41 | - if (!empty($reviews)) { |
|
| 42 | - array_walk($reviews, function (&$review) { |
|
| 43 | - unset($review['@context']); |
|
| 44 | - unset($review['itemReviewed']); |
|
| 45 | - }); |
|
| 46 | - $schema['review'] = $reviews; |
|
| 47 | - } |
|
| 48 | - return $schema; |
|
| 49 | - } |
|
| 25 | + /** |
|
| 26 | + * @return array |
|
| 27 | + */ |
|
| 28 | + public function build(array $args = []) |
|
| 29 | + { |
|
| 30 | + $this->args = $args; |
|
| 31 | + $schema = $this->buildSummary($args); |
|
| 32 | + $reviews = []; |
|
| 33 | + foreach (glsr(ReviewManager::class)->get($this->args) as $review) { |
|
| 34 | + // Only include critic reviews that have been directly produced by your site, not reviews from third-party sites or syndicated reviews. |
|
| 35 | + // @see https://developers.google.com/search/docs/data-types/review |
|
| 36 | + if ('local' != $review->review_type) { |
|
| 37 | + continue; |
|
| 38 | + } |
|
| 39 | + $reviews[] = $this->buildReview($review); |
|
| 40 | + } |
|
| 41 | + if (!empty($reviews)) { |
|
| 42 | + array_walk($reviews, function (&$review) { |
|
| 43 | + unset($review['@context']); |
|
| 44 | + unset($review['itemReviewed']); |
|
| 45 | + }); |
|
| 46 | + $schema['review'] = $reviews; |
|
| 47 | + } |
|
| 48 | + return $schema; |
|
| 49 | + } |
|
| 50 | 50 | |
| 51 | - /** |
|
| 52 | - * @param array|null $args |
|
| 53 | - * @return array |
|
| 54 | - */ |
|
| 55 | - public function buildSummary($args = null) |
|
| 56 | - { |
|
| 57 | - if (is_array($args)) { |
|
| 58 | - $this->args = $args; |
|
| 59 | - } |
|
| 60 | - $buildSummary = glsr(Helper::class)->buildMethodName($this->getSchemaOptionValue('type'), 'buildSummaryFor'); |
|
| 61 | - $count = array_sum($this->getRatingCounts()); |
|
| 62 | - $schema = method_exists($this, $buildSummary) |
|
| 63 | - ? $this->$buildSummary() |
|
| 64 | - : $this->buildSummaryForCustom(); |
|
| 65 | - if (!empty($count)) { |
|
| 66 | - $schema->aggregateRating( |
|
| 67 | - $this->getSchemaType('AggregateRating') |
|
| 68 | - ->ratingValue($this->getRatingValue()) |
|
| 69 | - ->reviewCount($count) |
|
| 70 | - ->bestRating(glsr()->constant('MAX_RATING', Rating::class)) |
|
| 71 | - ->worstRating(glsr()->constant('MIN_RATING', Rating::class)) |
|
| 72 | - ); |
|
| 73 | - } |
|
| 74 | - $schema = $schema->toArray(); |
|
| 75 | - return apply_filters('site-reviews/schema/'.$schema['@type'], $schema, $args); |
|
| 76 | - } |
|
| 51 | + /** |
|
| 52 | + * @param array|null $args |
|
| 53 | + * @return array |
|
| 54 | + */ |
|
| 55 | + public function buildSummary($args = null) |
|
| 56 | + { |
|
| 57 | + if (is_array($args)) { |
|
| 58 | + $this->args = $args; |
|
| 59 | + } |
|
| 60 | + $buildSummary = glsr(Helper::class)->buildMethodName($this->getSchemaOptionValue('type'), 'buildSummaryFor'); |
|
| 61 | + $count = array_sum($this->getRatingCounts()); |
|
| 62 | + $schema = method_exists($this, $buildSummary) |
|
| 63 | + ? $this->$buildSummary() |
|
| 64 | + : $this->buildSummaryForCustom(); |
|
| 65 | + if (!empty($count)) { |
|
| 66 | + $schema->aggregateRating( |
|
| 67 | + $this->getSchemaType('AggregateRating') |
|
| 68 | + ->ratingValue($this->getRatingValue()) |
|
| 69 | + ->reviewCount($count) |
|
| 70 | + ->bestRating(glsr()->constant('MAX_RATING', Rating::class)) |
|
| 71 | + ->worstRating(glsr()->constant('MIN_RATING', Rating::class)) |
|
| 72 | + ); |
|
| 73 | + } |
|
| 74 | + $schema = $schema->toArray(); |
|
| 75 | + return apply_filters('site-reviews/schema/'.$schema['@type'], $schema, $args); |
|
| 76 | + } |
|
| 77 | 77 | |
| 78 | - /** |
|
| 79 | - * @return void |
|
| 80 | - */ |
|
| 81 | - public function render() |
|
| 82 | - { |
|
| 83 | - if (empty(glsr()->schemas)) { |
|
| 84 | - return; |
|
| 85 | - } |
|
| 86 | - printf('<script type="application/ld+json">%s</script>', json_encode( |
|
| 87 | - apply_filters('site-reviews/schema/all', glsr()->schemas), |
|
| 88 | - JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES |
|
| 89 | - )); |
|
| 90 | - } |
|
| 78 | + /** |
|
| 79 | + * @return void |
|
| 80 | + */ |
|
| 81 | + public function render() |
|
| 82 | + { |
|
| 83 | + if (empty(glsr()->schemas)) { |
|
| 84 | + return; |
|
| 85 | + } |
|
| 86 | + printf('<script type="application/ld+json">%s</script>', json_encode( |
|
| 87 | + apply_filters('site-reviews/schema/all', glsr()->schemas), |
|
| 88 | + JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES |
|
| 89 | + )); |
|
| 90 | + } |
|
| 91 | 91 | |
| 92 | - /** |
|
| 93 | - * @return void |
|
| 94 | - */ |
|
| 95 | - public function store(array $schema) |
|
| 96 | - { |
|
| 97 | - $schemas = glsr()->schemas; |
|
| 98 | - $schemas[] = $schema; |
|
| 99 | - glsr()->schemas = array_map('unserialize', array_unique(array_map('serialize', $schemas))); |
|
| 100 | - } |
|
| 92 | + /** |
|
| 93 | + * @return void |
|
| 94 | + */ |
|
| 95 | + public function store(array $schema) |
|
| 96 | + { |
|
| 97 | + $schemas = glsr()->schemas; |
|
| 98 | + $schemas[] = $schema; |
|
| 99 | + glsr()->schemas = array_map('unserialize', array_unique(array_map('serialize', $schemas))); |
|
| 100 | + } |
|
| 101 | 101 | |
| 102 | - /** |
|
| 103 | - * @param Review $review |
|
| 104 | - * @return array |
|
| 105 | - */ |
|
| 106 | - protected function buildReview($review) |
|
| 107 | - { |
|
| 108 | - $schema = $this->getSchemaType('Review') |
|
| 109 | - ->doIf(!in_array('title', $this->args['hide']), function ($schema) use ($review) { |
|
| 110 | - $schema->name($review->title); |
|
| 111 | - }) |
|
| 112 | - ->doIf(!in_array('excerpt', $this->args['hide']), function ($schema) use ($review) { |
|
| 113 | - $schema->reviewBody($review->content); |
|
| 114 | - }) |
|
| 115 | - ->datePublished(( new DateTime($review->date))) |
|
| 116 | - ->author($this->getSchemaType('Person')->name($review->author)) |
|
| 117 | - ->itemReviewed($this->getSchemaType()->name($this->getSchemaOptionValue('name'))); |
|
| 118 | - if (!empty($review->rating)) { |
|
| 119 | - $schema->reviewRating( |
|
| 120 | - $this->getSchemaType('Rating') |
|
| 121 | - ->ratingValue($review->rating) |
|
| 122 | - ->bestRating(glsr()->constant('MAX_RATING', Rating::class)) |
|
| 123 | - ->worstRating(glsr()->constant('MIN_RATING', Rating::class)) |
|
| 124 | - ); |
|
| 125 | - } |
|
| 126 | - return apply_filters('site-reviews/schema/review', $schema->toArray(), $review, $this->args); |
|
| 127 | - } |
|
| 102 | + /** |
|
| 103 | + * @param Review $review |
|
| 104 | + * @return array |
|
| 105 | + */ |
|
| 106 | + protected function buildReview($review) |
|
| 107 | + { |
|
| 108 | + $schema = $this->getSchemaType('Review') |
|
| 109 | + ->doIf(!in_array('title', $this->args['hide']), function ($schema) use ($review) { |
|
| 110 | + $schema->name($review->title); |
|
| 111 | + }) |
|
| 112 | + ->doIf(!in_array('excerpt', $this->args['hide']), function ($schema) use ($review) { |
|
| 113 | + $schema->reviewBody($review->content); |
|
| 114 | + }) |
|
| 115 | + ->datePublished(( new DateTime($review->date))) |
|
| 116 | + ->author($this->getSchemaType('Person')->name($review->author)) |
|
| 117 | + ->itemReviewed($this->getSchemaType()->name($this->getSchemaOptionValue('name'))); |
|
| 118 | + if (!empty($review->rating)) { |
|
| 119 | + $schema->reviewRating( |
|
| 120 | + $this->getSchemaType('Rating') |
|
| 121 | + ->ratingValue($review->rating) |
|
| 122 | + ->bestRating(glsr()->constant('MAX_RATING', Rating::class)) |
|
| 123 | + ->worstRating(glsr()->constant('MIN_RATING', Rating::class)) |
|
| 124 | + ); |
|
| 125 | + } |
|
| 126 | + return apply_filters('site-reviews/schema/review', $schema->toArray(), $review, $this->args); |
|
| 127 | + } |
|
| 128 | 128 | |
| 129 | - /** |
|
| 130 | - * @param mixed $schema |
|
| 131 | - * @return mixed |
|
| 132 | - */ |
|
| 133 | - protected function buildSchemaValues($schema, array $values = []) |
|
| 134 | - { |
|
| 135 | - foreach ($values as $value) { |
|
| 136 | - $option = $this->getSchemaOptionValue($value); |
|
| 137 | - if (empty($option)) { |
|
| 138 | - continue; |
|
| 139 | - } |
|
| 140 | - $schema->$value($option); |
|
| 141 | - } |
|
| 142 | - return $schema; |
|
| 143 | - } |
|
| 129 | + /** |
|
| 130 | + * @param mixed $schema |
|
| 131 | + * @return mixed |
|
| 132 | + */ |
|
| 133 | + protected function buildSchemaValues($schema, array $values = []) |
|
| 134 | + { |
|
| 135 | + foreach ($values as $value) { |
|
| 136 | + $option = $this->getSchemaOptionValue($value); |
|
| 137 | + if (empty($option)) { |
|
| 138 | + continue; |
|
| 139 | + } |
|
| 140 | + $schema->$value($option); |
|
| 141 | + } |
|
| 142 | + return $schema; |
|
| 143 | + } |
|
| 144 | 144 | |
| 145 | - /** |
|
| 146 | - * @return mixed |
|
| 147 | - */ |
|
| 148 | - protected function buildSummaryForCustom() |
|
| 149 | - { |
|
| 150 | - return $this->buildSchemaValues($this->getSchemaType(), [ |
|
| 151 | - 'description', 'image', 'name', 'url', |
|
| 152 | - ]); |
|
| 153 | - } |
|
| 145 | + /** |
|
| 146 | + * @return mixed |
|
| 147 | + */ |
|
| 148 | + protected function buildSummaryForCustom() |
|
| 149 | + { |
|
| 150 | + return $this->buildSchemaValues($this->getSchemaType(), [ |
|
| 151 | + 'description', 'image', 'name', 'url', |
|
| 152 | + ]); |
|
| 153 | + } |
|
| 154 | 154 | |
| 155 | - /** |
|
| 156 | - * @return mixed |
|
| 157 | - */ |
|
| 158 | - protected function buildSummaryForLocalBusiness() |
|
| 159 | - { |
|
| 160 | - return $this->buildSchemaValues($this->buildSummaryForCustom(), [ |
|
| 161 | - 'address', 'priceRange', 'telephone', |
|
| 162 | - ]); |
|
| 163 | - } |
|
| 155 | + /** |
|
| 156 | + * @return mixed |
|
| 157 | + */ |
|
| 158 | + protected function buildSummaryForLocalBusiness() |
|
| 159 | + { |
|
| 160 | + return $this->buildSchemaValues($this->buildSummaryForCustom(), [ |
|
| 161 | + 'address', 'priceRange', 'telephone', |
|
| 162 | + ]); |
|
| 163 | + } |
|
| 164 | 164 | |
| 165 | - /** |
|
| 166 | - * @return mixed |
|
| 167 | - */ |
|
| 168 | - protected function buildSummaryForProduct() |
|
| 169 | - { |
|
| 170 | - $offerType = $this->getSchemaOption('offerType', 'AggregateOffer'); |
|
| 171 | - $offers = $this->buildSchemaValues($this->getSchemaType($offerType), [ |
|
| 172 | - 'highPrice', 'lowPrice', 'price', 'priceCurrency', |
|
| 173 | - ]); |
|
| 174 | - return $this->buildSummaryForCustom() |
|
| 175 | - ->doIf(!empty($offers->getProperties()), function ($schema) use ($offers) { |
|
| 176 | - $schema->offers($offers); |
|
| 177 | - }) |
|
| 178 | - ->setProperty('@id', $this->getSchemaOptionValue('url').'#product'); |
|
| 179 | - } |
|
| 165 | + /** |
|
| 166 | + * @return mixed |
|
| 167 | + */ |
|
| 168 | + protected function buildSummaryForProduct() |
|
| 169 | + { |
|
| 170 | + $offerType = $this->getSchemaOption('offerType', 'AggregateOffer'); |
|
| 171 | + $offers = $this->buildSchemaValues($this->getSchemaType($offerType), [ |
|
| 172 | + 'highPrice', 'lowPrice', 'price', 'priceCurrency', |
|
| 173 | + ]); |
|
| 174 | + return $this->buildSummaryForCustom() |
|
| 175 | + ->doIf(!empty($offers->getProperties()), function ($schema) use ($offers) { |
|
| 176 | + $schema->offers($offers); |
|
| 177 | + }) |
|
| 178 | + ->setProperty('@id', $this->getSchemaOptionValue('url').'#product'); |
|
| 179 | + } |
|
| 180 | 180 | |
| 181 | - /** |
|
| 182 | - * @return array |
|
| 183 | - */ |
|
| 184 | - protected function getRatingCounts() |
|
| 185 | - { |
|
| 186 | - if (!isset($this->ratingCounts)) { |
|
| 187 | - $this->ratingCounts = glsr(ReviewManager::class)->getRatingCounts($this->args); |
|
| 188 | - } |
|
| 189 | - return $this->ratingCounts; |
|
| 190 | - } |
|
| 181 | + /** |
|
| 182 | + * @return array |
|
| 183 | + */ |
|
| 184 | + protected function getRatingCounts() |
|
| 185 | + { |
|
| 186 | + if (!isset($this->ratingCounts)) { |
|
| 187 | + $this->ratingCounts = glsr(ReviewManager::class)->getRatingCounts($this->args); |
|
| 188 | + } |
|
| 189 | + return $this->ratingCounts; |
|
| 190 | + } |
|
| 191 | 191 | |
| 192 | - /** |
|
| 193 | - * @return int|float |
|
| 194 | - */ |
|
| 195 | - protected function getRatingValue() |
|
| 196 | - { |
|
| 197 | - return glsr(Rating::class)->getAverage($this->getRatingCounts()); |
|
| 198 | - } |
|
| 192 | + /** |
|
| 193 | + * @return int|float |
|
| 194 | + */ |
|
| 195 | + protected function getRatingValue() |
|
| 196 | + { |
|
| 197 | + return glsr(Rating::class)->getAverage($this->getRatingCounts()); |
|
| 198 | + } |
|
| 199 | 199 | |
| 200 | - /** |
|
| 201 | - * @param string $option |
|
| 202 | - * @param string $fallback |
|
| 203 | - * @return string |
|
| 204 | - */ |
|
| 205 | - protected function getSchemaOption($option, $fallback) |
|
| 206 | - { |
|
| 207 | - $option = strtolower($option); |
|
| 208 | - if ($schemaOption = trim((string) get_post_meta(intval(get_the_ID()), 'schema_'.$option, true))) { |
|
| 209 | - return $schemaOption; |
|
| 210 | - } |
|
| 211 | - $setting = glsr(OptionManager::class)->get('settings.schema.'.$option); |
|
| 212 | - if (is_array($setting)) { |
|
| 213 | - return $this->getSchemaOptionDefault($setting, $fallback); |
|
| 214 | - } |
|
| 215 | - return !empty($setting) |
|
| 216 | - ? $setting |
|
| 217 | - : $fallback; |
|
| 218 | - } |
|
| 200 | + /** |
|
| 201 | + * @param string $option |
|
| 202 | + * @param string $fallback |
|
| 203 | + * @return string |
|
| 204 | + */ |
|
| 205 | + protected function getSchemaOption($option, $fallback) |
|
| 206 | + { |
|
| 207 | + $option = strtolower($option); |
|
| 208 | + if ($schemaOption = trim((string) get_post_meta(intval(get_the_ID()), 'schema_'.$option, true))) { |
|
| 209 | + return $schemaOption; |
|
| 210 | + } |
|
| 211 | + $setting = glsr(OptionManager::class)->get('settings.schema.'.$option); |
|
| 212 | + if (is_array($setting)) { |
|
| 213 | + return $this->getSchemaOptionDefault($setting, $fallback); |
|
| 214 | + } |
|
| 215 | + return !empty($setting) |
|
| 216 | + ? $setting |
|
| 217 | + : $fallback; |
|
| 218 | + } |
|
| 219 | 219 | |
| 220 | - /** |
|
| 221 | - * @param string $fallback |
|
| 222 | - * @return string |
|
| 223 | - */ |
|
| 224 | - protected function getSchemaOptionDefault(array $setting, $fallback) |
|
| 225 | - { |
|
| 226 | - $setting = wp_parse_args($setting, [ |
|
| 227 | - 'custom' => '', |
|
| 228 | - 'default' => $fallback, |
|
| 229 | - ]); |
|
| 230 | - return 'custom' != $setting['default'] |
|
| 231 | - ? $setting['default'] |
|
| 232 | - : $setting['custom']; |
|
| 233 | - } |
|
| 220 | + /** |
|
| 221 | + * @param string $fallback |
|
| 222 | + * @return string |
|
| 223 | + */ |
|
| 224 | + protected function getSchemaOptionDefault(array $setting, $fallback) |
|
| 225 | + { |
|
| 226 | + $setting = wp_parse_args($setting, [ |
|
| 227 | + 'custom' => '', |
|
| 228 | + 'default' => $fallback, |
|
| 229 | + ]); |
|
| 230 | + return 'custom' != $setting['default'] |
|
| 231 | + ? $setting['default'] |
|
| 232 | + : $setting['custom']; |
|
| 233 | + } |
|
| 234 | 234 | |
| 235 | - /** |
|
| 236 | - * @param string $option |
|
| 237 | - * @param string $fallback |
|
| 238 | - * @return void|string |
|
| 239 | - */ |
|
| 240 | - protected function getSchemaOptionValue($option, $fallback = 'post') |
|
| 241 | - { |
|
| 242 | - $value = $this->getSchemaOption($option, $fallback); |
|
| 243 | - if ($value != $fallback) { |
|
| 244 | - return $value; |
|
| 245 | - } |
|
| 246 | - if (!is_single() && !is_page()) { |
|
| 247 | - return; |
|
| 248 | - } |
|
| 249 | - $method = glsr(Helper::class)->buildMethodName($option, 'getThing'); |
|
| 250 | - if (method_exists($this, $method)) { |
|
| 251 | - return $this->$method(); |
|
| 252 | - } |
|
| 253 | - } |
|
| 235 | + /** |
|
| 236 | + * @param string $option |
|
| 237 | + * @param string $fallback |
|
| 238 | + * @return void|string |
|
| 239 | + */ |
|
| 240 | + protected function getSchemaOptionValue($option, $fallback = 'post') |
|
| 241 | + { |
|
| 242 | + $value = $this->getSchemaOption($option, $fallback); |
|
| 243 | + if ($value != $fallback) { |
|
| 244 | + return $value; |
|
| 245 | + } |
|
| 246 | + if (!is_single() && !is_page()) { |
|
| 247 | + return; |
|
| 248 | + } |
|
| 249 | + $method = glsr(Helper::class)->buildMethodName($option, 'getThing'); |
|
| 250 | + if (method_exists($this, $method)) { |
|
| 251 | + return $this->$method(); |
|
| 252 | + } |
|
| 253 | + } |
|
| 254 | 254 | |
| 255 | - /** |
|
| 256 | - * @param string|null $type |
|
| 257 | - * @return mixed |
|
| 258 | - */ |
|
| 259 | - protected function getSchemaType($type = null) |
|
| 260 | - { |
|
| 261 | - if (!is_string($type)) { |
|
| 262 | - $type = $this->getSchemaOption('type', 'LocalBusiness'); |
|
| 263 | - } |
|
| 264 | - $className = glsr(Helper::class)->buildClassName($type, 'Modules\Schema'); |
|
| 265 | - return class_exists($className) |
|
| 266 | - ? new $className() |
|
| 267 | - : new UnknownType($type); |
|
| 268 | - } |
|
| 255 | + /** |
|
| 256 | + * @param string|null $type |
|
| 257 | + * @return mixed |
|
| 258 | + */ |
|
| 259 | + protected function getSchemaType($type = null) |
|
| 260 | + { |
|
| 261 | + if (!is_string($type)) { |
|
| 262 | + $type = $this->getSchemaOption('type', 'LocalBusiness'); |
|
| 263 | + } |
|
| 264 | + $className = glsr(Helper::class)->buildClassName($type, 'Modules\Schema'); |
|
| 265 | + return class_exists($className) |
|
| 266 | + ? new $className() |
|
| 267 | + : new UnknownType($type); |
|
| 268 | + } |
|
| 269 | 269 | |
| 270 | - /** |
|
| 271 | - * @return string |
|
| 272 | - */ |
|
| 273 | - protected function getThingDescription() |
|
| 274 | - { |
|
| 275 | - $post = get_post(); |
|
| 276 | - if (!($post instanceof WP_Post)) { |
|
| 277 | - return ''; |
|
| 278 | - } |
|
| 279 | - $text = strip_shortcodes(wp_strip_all_tags($post->post_excerpt)); |
|
| 280 | - return wp_trim_words($text, apply_filters('excerpt_length', 55)); |
|
| 281 | - } |
|
| 270 | + /** |
|
| 271 | + * @return string |
|
| 272 | + */ |
|
| 273 | + protected function getThingDescription() |
|
| 274 | + { |
|
| 275 | + $post = get_post(); |
|
| 276 | + if (!($post instanceof WP_Post)) { |
|
| 277 | + return ''; |
|
| 278 | + } |
|
| 279 | + $text = strip_shortcodes(wp_strip_all_tags($post->post_excerpt)); |
|
| 280 | + return wp_trim_words($text, apply_filters('excerpt_length', 55)); |
|
| 281 | + } |
|
| 282 | 282 | |
| 283 | - /** |
|
| 284 | - * @return string |
|
| 285 | - */ |
|
| 286 | - protected function getThingImage() |
|
| 287 | - { |
|
| 288 | - return (string) get_the_post_thumbnail_url(null, 'large'); |
|
| 289 | - } |
|
| 283 | + /** |
|
| 284 | + * @return string |
|
| 285 | + */ |
|
| 286 | + protected function getThingImage() |
|
| 287 | + { |
|
| 288 | + return (string) get_the_post_thumbnail_url(null, 'large'); |
|
| 289 | + } |
|
| 290 | 290 | |
| 291 | - /** |
|
| 292 | - * @return string |
|
| 293 | - */ |
|
| 294 | - protected function getThingName() |
|
| 295 | - { |
|
| 296 | - return get_the_title(); |
|
| 297 | - } |
|
| 291 | + /** |
|
| 292 | + * @return string |
|
| 293 | + */ |
|
| 294 | + protected function getThingName() |
|
| 295 | + { |
|
| 296 | + return get_the_title(); |
|
| 297 | + } |
|
| 298 | 298 | |
| 299 | - /** |
|
| 300 | - * @return string |
|
| 301 | - */ |
|
| 302 | - protected function getThingUrl() |
|
| 303 | - { |
|
| 304 | - return (string) get_the_permalink(); |
|
| 305 | - } |
|
| 299 | + /** |
|
| 300 | + * @return string |
|
| 301 | + */ |
|
| 302 | + protected function getThingUrl() |
|
| 303 | + { |
|
| 304 | + return (string) get_the_permalink(); |
|
| 305 | + } |
|
| 306 | 306 | } |
@@ -9,126 +9,126 @@ |
||
| 9 | 9 | */ |
| 10 | 10 | trait ValidationRules |
| 11 | 11 | { |
| 12 | - /** |
|
| 13 | - * Get the size of an attribute. |
|
| 14 | - * @param string $attribute |
|
| 15 | - * @param mixed $value |
|
| 16 | - * @return mixed |
|
| 17 | - */ |
|
| 18 | - abstract protected function getSize($attribute, $value); |
|
| 12 | + /** |
|
| 13 | + * Get the size of an attribute. |
|
| 14 | + * @param string $attribute |
|
| 15 | + * @param mixed $value |
|
| 16 | + * @return mixed |
|
| 17 | + */ |
|
| 18 | + abstract protected function getSize($attribute, $value); |
|
| 19 | 19 | |
| 20 | - /** |
|
| 21 | - * Replace all placeholders. |
|
| 22 | - * @param string $message |
|
| 23 | - * @return string |
|
| 24 | - */ |
|
| 25 | - protected function replace($message, array $parameters) |
|
| 26 | - { |
|
| 27 | - if (false === strpos($message, '%s')) { |
|
| 28 | - return $message; |
|
| 29 | - } |
|
| 30 | - return preg_replace_callback('/(%s)/', function () use (&$parameters) { |
|
| 31 | - foreach ($parameters as $key => $value) { |
|
| 32 | - return array_shift($parameters); |
|
| 33 | - } |
|
| 34 | - }, $message); |
|
| 35 | - } |
|
| 20 | + /** |
|
| 21 | + * Replace all placeholders. |
|
| 22 | + * @param string $message |
|
| 23 | + * @return string |
|
| 24 | + */ |
|
| 25 | + protected function replace($message, array $parameters) |
|
| 26 | + { |
|
| 27 | + if (false === strpos($message, '%s')) { |
|
| 28 | + return $message; |
|
| 29 | + } |
|
| 30 | + return preg_replace_callback('/(%s)/', function () use (&$parameters) { |
|
| 31 | + foreach ($parameters as $key => $value) { |
|
| 32 | + return array_shift($parameters); |
|
| 33 | + } |
|
| 34 | + }, $message); |
|
| 35 | + } |
|
| 36 | 36 | |
| 37 | - /** |
|
| 38 | - * Validate that an attribute was "accepted". |
|
| 39 | - * This validation rule implies the attribute is "required". |
|
| 40 | - * @param string $attribute |
|
| 41 | - * @param mixed $value |
|
| 42 | - * @return bool |
|
| 43 | - */ |
|
| 44 | - public function validateAccepted($value) |
|
| 45 | - { |
|
| 46 | - $acceptable = ['yes', 'on', '1', 1, true, 'true']; |
|
| 47 | - return $this->validateRequired($value) && in_array($value, $acceptable, true); |
|
| 48 | - } |
|
| 37 | + /** |
|
| 38 | + * Validate that an attribute was "accepted". |
|
| 39 | + * This validation rule implies the attribute is "required". |
|
| 40 | + * @param string $attribute |
|
| 41 | + * @param mixed $value |
|
| 42 | + * @return bool |
|
| 43 | + */ |
|
| 44 | + public function validateAccepted($value) |
|
| 45 | + { |
|
| 46 | + $acceptable = ['yes', 'on', '1', 1, true, 'true']; |
|
| 47 | + return $this->validateRequired($value) && in_array($value, $acceptable, true); |
|
| 48 | + } |
|
| 49 | 49 | |
| 50 | - /** |
|
| 51 | - * Validate the size of an attribute is between a set of values. |
|
| 52 | - * @param string $attribute |
|
| 53 | - * @param mixed $value |
|
| 54 | - * @return bool |
|
| 55 | - */ |
|
| 56 | - public function validateBetween($value, $attribute, array $parameters) |
|
| 57 | - { |
|
| 58 | - $this->requireParameterCount(2, $parameters, 'between'); |
|
| 59 | - $size = $this->getSize($attribute, $value); |
|
| 60 | - return $size >= $parameters[0] && $size <= $parameters[1]; |
|
| 61 | - } |
|
| 50 | + /** |
|
| 51 | + * Validate the size of an attribute is between a set of values. |
|
| 52 | + * @param string $attribute |
|
| 53 | + * @param mixed $value |
|
| 54 | + * @return bool |
|
| 55 | + */ |
|
| 56 | + public function validateBetween($value, $attribute, array $parameters) |
|
| 57 | + { |
|
| 58 | + $this->requireParameterCount(2, $parameters, 'between'); |
|
| 59 | + $size = $this->getSize($attribute, $value); |
|
| 60 | + return $size >= $parameters[0] && $size <= $parameters[1]; |
|
| 61 | + } |
|
| 62 | 62 | |
| 63 | - /** |
|
| 64 | - * Validate that an attribute is a valid e-mail address. |
|
| 65 | - * @param mixed $value |
|
| 66 | - * @return bool |
|
| 67 | - */ |
|
| 68 | - public function validateEmail($value) |
|
| 69 | - { |
|
| 70 | - return false !== filter_var($value, FILTER_VALIDATE_EMAIL); |
|
| 71 | - } |
|
| 63 | + /** |
|
| 64 | + * Validate that an attribute is a valid e-mail address. |
|
| 65 | + * @param mixed $value |
|
| 66 | + * @return bool |
|
| 67 | + */ |
|
| 68 | + public function validateEmail($value) |
|
| 69 | + { |
|
| 70 | + return false !== filter_var($value, FILTER_VALIDATE_EMAIL); |
|
| 71 | + } |
|
| 72 | 72 | |
| 73 | - /** |
|
| 74 | - * Validate the size of an attribute is less than a maximum value. |
|
| 75 | - * @param string $attribute |
|
| 76 | - * @param mixed $value |
|
| 77 | - * @return bool |
|
| 78 | - */ |
|
| 79 | - public function validateMax($value, $attribute, array $parameters) |
|
| 80 | - { |
|
| 81 | - $this->requireParameterCount(1, $parameters, 'max'); |
|
| 82 | - return $this->getSize($attribute, $value) <= $parameters[0]; |
|
| 83 | - } |
|
| 73 | + /** |
|
| 74 | + * Validate the size of an attribute is less than a maximum value. |
|
| 75 | + * @param string $attribute |
|
| 76 | + * @param mixed $value |
|
| 77 | + * @return bool |
|
| 78 | + */ |
|
| 79 | + public function validateMax($value, $attribute, array $parameters) |
|
| 80 | + { |
|
| 81 | + $this->requireParameterCount(1, $parameters, 'max'); |
|
| 82 | + return $this->getSize($attribute, $value) <= $parameters[0]; |
|
| 83 | + } |
|
| 84 | 84 | |
| 85 | - /** |
|
| 86 | - * Validate the size of an attribute is greater than a minimum value. |
|
| 87 | - * @param string $attribute |
|
| 88 | - * @param mixed $value |
|
| 89 | - * @return bool |
|
| 90 | - */ |
|
| 91 | - public function validateMin($value, $attribute, array $parameters) |
|
| 92 | - { |
|
| 93 | - $this->requireParameterCount(1, $parameters, 'min'); |
|
| 94 | - return $this->getSize($attribute, $value) >= $parameters[0]; |
|
| 95 | - } |
|
| 85 | + /** |
|
| 86 | + * Validate the size of an attribute is greater than a minimum value. |
|
| 87 | + * @param string $attribute |
|
| 88 | + * @param mixed $value |
|
| 89 | + * @return bool |
|
| 90 | + */ |
|
| 91 | + public function validateMin($value, $attribute, array $parameters) |
|
| 92 | + { |
|
| 93 | + $this->requireParameterCount(1, $parameters, 'min'); |
|
| 94 | + return $this->getSize($attribute, $value) >= $parameters[0]; |
|
| 95 | + } |
|
| 96 | 96 | |
| 97 | - /** |
|
| 98 | - * Validate that an attribute is numeric. |
|
| 99 | - * @param mixed $value |
|
| 100 | - * @return bool |
|
| 101 | - */ |
|
| 102 | - public function validateNumber($value) |
|
| 103 | - { |
|
| 104 | - return is_numeric($value); |
|
| 105 | - } |
|
| 97 | + /** |
|
| 98 | + * Validate that an attribute is numeric. |
|
| 99 | + * @param mixed $value |
|
| 100 | + * @return bool |
|
| 101 | + */ |
|
| 102 | + public function validateNumber($value) |
|
| 103 | + { |
|
| 104 | + return is_numeric($value); |
|
| 105 | + } |
|
| 106 | 106 | |
| 107 | - /** |
|
| 108 | - * Validate that a required attribute exists. |
|
| 109 | - * @param mixed $value |
|
| 110 | - * @return bool |
|
| 111 | - */ |
|
| 112 | - public function validateRequired($value) |
|
| 113 | - { |
|
| 114 | - return is_null($value) |
|
| 115 | - || (is_string($value) && '' === trim($value)) |
|
| 116 | - || (is_array($value) && count($value) < 1) |
|
| 117 | - ? false |
|
| 118 | - : true; |
|
| 119 | - } |
|
| 107 | + /** |
|
| 108 | + * Validate that a required attribute exists. |
|
| 109 | + * @param mixed $value |
|
| 110 | + * @return bool |
|
| 111 | + */ |
|
| 112 | + public function validateRequired($value) |
|
| 113 | + { |
|
| 114 | + return is_null($value) |
|
| 115 | + || (is_string($value) && '' === trim($value)) |
|
| 116 | + || (is_array($value) && count($value) < 1) |
|
| 117 | + ? false |
|
| 118 | + : true; |
|
| 119 | + } |
|
| 120 | 120 | |
| 121 | - /** |
|
| 122 | - * Require a certain number of parameters to be present. |
|
| 123 | - * @param int $count |
|
| 124 | - * @param string $rule |
|
| 125 | - * @return void |
|
| 126 | - * @throws InvalidArgumentException |
|
| 127 | - */ |
|
| 128 | - protected function requireParameterCount($count, array $parameters, $rule) |
|
| 129 | - { |
|
| 130 | - if (count($parameters) < $count) { |
|
| 131 | - throw new InvalidArgumentException("Validation rule $rule requires at least $count parameters."); |
|
| 132 | - } |
|
| 133 | - } |
|
| 121 | + /** |
|
| 122 | + * Require a certain number of parameters to be present. |
|
| 123 | + * @param int $count |
|
| 124 | + * @param string $rule |
|
| 125 | + * @return void |
|
| 126 | + * @throws InvalidArgumentException |
|
| 127 | + */ |
|
| 128 | + protected function requireParameterCount($count, array $parameters, $rule) |
|
| 129 | + { |
|
| 130 | + if (count($parameters) < $count) { |
|
| 131 | + throw new InvalidArgumentException("Validation rule $rule requires at least $count parameters."); |
|
| 132 | + } |
|
| 133 | + } |
|
| 134 | 134 | } |
@@ -12,265 +12,265 @@ |
||
| 12 | 12 | |
| 13 | 13 | class ValidateReview |
| 14 | 14 | { |
| 15 | - const RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify'; |
|
| 15 | + const RECAPTCHA_ENDPOINT = 'https://www.google.com/recaptcha/api/siteverify'; |
|
| 16 | 16 | |
| 17 | - const RECAPTCHA_DISABLED = 0; |
|
| 18 | - const RECAPTCHA_EMPTY = 1; |
|
| 19 | - const RECAPTCHA_FAILED = 2; |
|
| 20 | - const RECAPTCHA_INVALID = 3; |
|
| 21 | - const RECAPTCHA_VALID = 4; |
|
| 17 | + const RECAPTCHA_DISABLED = 0; |
|
| 18 | + const RECAPTCHA_EMPTY = 1; |
|
| 19 | + const RECAPTCHA_FAILED = 2; |
|
| 20 | + const RECAPTCHA_INVALID = 3; |
|
| 21 | + const RECAPTCHA_VALID = 4; |
|
| 22 | 22 | |
| 23 | - const VALIDATION_RULES = [ |
|
| 24 | - 'content' => 'required', |
|
| 25 | - 'email' => 'required|email', |
|
| 26 | - 'name' => 'required', |
|
| 27 | - 'rating' => 'required|number|between:1,5', |
|
| 28 | - 'terms' => 'accepted', |
|
| 29 | - 'title' => 'required', |
|
| 30 | - ]; |
|
| 23 | + const VALIDATION_RULES = [ |
|
| 24 | + 'content' => 'required', |
|
| 25 | + 'email' => 'required|email', |
|
| 26 | + 'name' => 'required', |
|
| 27 | + 'rating' => 'required|number|between:1,5', |
|
| 28 | + 'terms' => 'accepted', |
|
| 29 | + 'title' => 'required', |
|
| 30 | + ]; |
|
| 31 | 31 | |
| 32 | - /** |
|
| 33 | - * @var string|void |
|
| 34 | - */ |
|
| 35 | - public $error; |
|
| 32 | + /** |
|
| 33 | + * @var string|void |
|
| 34 | + */ |
|
| 35 | + public $error; |
|
| 36 | 36 | |
| 37 | - /** |
|
| 38 | - * @var string |
|
| 39 | - */ |
|
| 40 | - public $form_id; |
|
| 37 | + /** |
|
| 38 | + * @var string |
|
| 39 | + */ |
|
| 40 | + public $form_id; |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * @var bool |
|
| 44 | - */ |
|
| 45 | - public $recaptchaIsUnset = false; |
|
| 42 | + /** |
|
| 43 | + * @var bool |
|
| 44 | + */ |
|
| 45 | + public $recaptchaIsUnset = false; |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * @var array |
|
| 49 | - */ |
|
| 50 | - public $request; |
|
| 47 | + /** |
|
| 48 | + * @var array |
|
| 49 | + */ |
|
| 50 | + public $request; |
|
| 51 | 51 | |
| 52 | - /** |
|
| 53 | - * @var array |
|
| 54 | - */ |
|
| 55 | - protected $options; |
|
| 52 | + /** |
|
| 53 | + * @var array |
|
| 54 | + */ |
|
| 55 | + protected $options; |
|
| 56 | 56 | |
| 57 | - /** |
|
| 58 | - * @return static |
|
| 59 | - */ |
|
| 60 | - public function validate(array $request) |
|
| 61 | - { |
|
| 62 | - $this->form_id = $request['form_id']; |
|
| 63 | - $this->options = glsr(OptionManager::class)->all(); |
|
| 64 | - $this->request = $this->validateRequest($request); |
|
| 65 | - $this->validateCustom(); |
|
| 66 | - $this->validateHoneyPot(); |
|
| 67 | - $this->validateBlacklist(); |
|
| 68 | - $this->validateAkismet(); |
|
| 69 | - $this->validateRecaptcha(); |
|
| 70 | - if (!empty($this->error)) { |
|
| 71 | - $this->setSessionValues('message', $this->error); |
|
| 72 | - } |
|
| 73 | - return $this; |
|
| 74 | - } |
|
| 57 | + /** |
|
| 58 | + * @return static |
|
| 59 | + */ |
|
| 60 | + public function validate(array $request) |
|
| 61 | + { |
|
| 62 | + $this->form_id = $request['form_id']; |
|
| 63 | + $this->options = glsr(OptionManager::class)->all(); |
|
| 64 | + $this->request = $this->validateRequest($request); |
|
| 65 | + $this->validateCustom(); |
|
| 66 | + $this->validateHoneyPot(); |
|
| 67 | + $this->validateBlacklist(); |
|
| 68 | + $this->validateAkismet(); |
|
| 69 | + $this->validateRecaptcha(); |
|
| 70 | + if (!empty($this->error)) { |
|
| 71 | + $this->setSessionValues('message', $this->error); |
|
| 72 | + } |
|
| 73 | + return $this; |
|
| 74 | + } |
|
| 75 | 75 | |
| 76 | - /** |
|
| 77 | - * @param string $path |
|
| 78 | - * @param mixed $fallback |
|
| 79 | - * @return mixed |
|
| 80 | - */ |
|
| 81 | - protected function getOption($path, $fallback = '') |
|
| 82 | - { |
|
| 83 | - return glsr(Helper::class)->dataGet($this->options, $path, $fallback); |
|
| 84 | - } |
|
| 76 | + /** |
|
| 77 | + * @param string $path |
|
| 78 | + * @param mixed $fallback |
|
| 79 | + * @return mixed |
|
| 80 | + */ |
|
| 81 | + protected function getOption($path, $fallback = '') |
|
| 82 | + { |
|
| 83 | + return glsr(Helper::class)->dataGet($this->options, $path, $fallback); |
|
| 84 | + } |
|
| 85 | 85 | |
| 86 | - /** |
|
| 87 | - * @return int |
|
| 88 | - */ |
|
| 89 | - protected function getRecaptchaStatus() |
|
| 90 | - { |
|
| 91 | - if (!glsr(OptionManager::class)->isRecaptchaEnabled()) { |
|
| 92 | - return static::RECAPTCHA_DISABLED; |
|
| 93 | - } |
|
| 94 | - if (empty($this->request['_recaptcha-token'])) { |
|
| 95 | - return $this->request['_counter'] < intval(apply_filters('site-reviews/recaptcha/timeout', 5)) |
|
| 96 | - ? static::RECAPTCHA_EMPTY |
|
| 97 | - : static::RECAPTCHA_FAILED; |
|
| 98 | - } |
|
| 99 | - return $this->getRecaptchaTokenStatus(); |
|
| 100 | - } |
|
| 86 | + /** |
|
| 87 | + * @return int |
|
| 88 | + */ |
|
| 89 | + protected function getRecaptchaStatus() |
|
| 90 | + { |
|
| 91 | + if (!glsr(OptionManager::class)->isRecaptchaEnabled()) { |
|
| 92 | + return static::RECAPTCHA_DISABLED; |
|
| 93 | + } |
|
| 94 | + if (empty($this->request['_recaptcha-token'])) { |
|
| 95 | + return $this->request['_counter'] < intval(apply_filters('site-reviews/recaptcha/timeout', 5)) |
|
| 96 | + ? static::RECAPTCHA_EMPTY |
|
| 97 | + : static::RECAPTCHA_FAILED; |
|
| 98 | + } |
|
| 99 | + return $this->getRecaptchaTokenStatus(); |
|
| 100 | + } |
|
| 101 | 101 | |
| 102 | - /** |
|
| 103 | - * @return int |
|
| 104 | - */ |
|
| 105 | - protected function getRecaptchaTokenStatus() |
|
| 106 | - { |
|
| 107 | - $endpoint = add_query_arg([ |
|
| 108 | - 'remoteip' => glsr(Helper::class)->getIpAddress(), |
|
| 109 | - 'response' => $this->request['_recaptcha-token'], |
|
| 110 | - 'secret' => $this->getOption('settings.submissions.recaptcha.secret'), |
|
| 111 | - ], static::RECAPTCHA_ENDPOINT); |
|
| 112 | - if (is_wp_error($response = wp_remote_get($endpoint))) { |
|
| 113 | - glsr_log()->error($response->get_error_message()); |
|
| 114 | - return static::RECAPTCHA_FAILED; |
|
| 115 | - } |
|
| 116 | - $response = json_decode(wp_remote_retrieve_body($response)); |
|
| 117 | - if (!empty($response->success)) { |
|
| 118 | - return boolval($response->success) |
|
| 119 | - ? static::RECAPTCHA_VALID |
|
| 120 | - : static::RECAPTCHA_INVALID; |
|
| 121 | - } |
|
| 122 | - foreach ($response->{'error-codes'} as $error) { |
|
| 123 | - glsr_log()->error('reCAPTCHA error: '.$error); |
|
| 124 | - } |
|
| 125 | - return static::RECAPTCHA_INVALID; |
|
| 126 | - } |
|
| 102 | + /** |
|
| 103 | + * @return int |
|
| 104 | + */ |
|
| 105 | + protected function getRecaptchaTokenStatus() |
|
| 106 | + { |
|
| 107 | + $endpoint = add_query_arg([ |
|
| 108 | + 'remoteip' => glsr(Helper::class)->getIpAddress(), |
|
| 109 | + 'response' => $this->request['_recaptcha-token'], |
|
| 110 | + 'secret' => $this->getOption('settings.submissions.recaptcha.secret'), |
|
| 111 | + ], static::RECAPTCHA_ENDPOINT); |
|
| 112 | + if (is_wp_error($response = wp_remote_get($endpoint))) { |
|
| 113 | + glsr_log()->error($response->get_error_message()); |
|
| 114 | + return static::RECAPTCHA_FAILED; |
|
| 115 | + } |
|
| 116 | + $response = json_decode(wp_remote_retrieve_body($response)); |
|
| 117 | + if (!empty($response->success)) { |
|
| 118 | + return boolval($response->success) |
|
| 119 | + ? static::RECAPTCHA_VALID |
|
| 120 | + : static::RECAPTCHA_INVALID; |
|
| 121 | + } |
|
| 122 | + foreach ($response->{'error-codes'} as $error) { |
|
| 123 | + glsr_log()->error('reCAPTCHA error: '.$error); |
|
| 124 | + } |
|
| 125 | + return static::RECAPTCHA_INVALID; |
|
| 126 | + } |
|
| 127 | 127 | |
| 128 | - /** |
|
| 129 | - * @return array |
|
| 130 | - */ |
|
| 131 | - protected function getValidationRules(array $request) |
|
| 132 | - { |
|
| 133 | - $rules = array_intersect_key( |
|
| 134 | - apply_filters('site-reviews/validation/rules', static::VALIDATION_RULES, $request), |
|
| 135 | - array_flip($this->getOption('settings.submissions.required', [])) |
|
| 136 | - ); |
|
| 137 | - $excluded = explode(',', glsr_get($request, 'excluded')); |
|
| 138 | - return array_diff_key($rules, array_flip($excluded)); |
|
| 139 | - } |
|
| 128 | + /** |
|
| 129 | + * @return array |
|
| 130 | + */ |
|
| 131 | + protected function getValidationRules(array $request) |
|
| 132 | + { |
|
| 133 | + $rules = array_intersect_key( |
|
| 134 | + apply_filters('site-reviews/validation/rules', static::VALIDATION_RULES, $request), |
|
| 135 | + array_flip($this->getOption('settings.submissions.required', [])) |
|
| 136 | + ); |
|
| 137 | + $excluded = explode(',', glsr_get($request, 'excluded')); |
|
| 138 | + return array_diff_key($rules, array_flip($excluded)); |
|
| 139 | + } |
|
| 140 | 140 | |
| 141 | - /** |
|
| 142 | - * @return bool |
|
| 143 | - */ |
|
| 144 | - protected function isRequestValid(array $request) |
|
| 145 | - { |
|
| 146 | - $rules = $this->getValidationRules($request); |
|
| 147 | - $errors = glsr(Validator::class)->validate($request, $rules); |
|
| 148 | - if (empty($errors)) { |
|
| 149 | - return true; |
|
| 150 | - } |
|
| 151 | - $this->setSessionValues('errors', $errors); |
|
| 152 | - $this->setSessionValues('values', $request); |
|
| 153 | - return false; |
|
| 154 | - } |
|
| 141 | + /** |
|
| 142 | + * @return bool |
|
| 143 | + */ |
|
| 144 | + protected function isRequestValid(array $request) |
|
| 145 | + { |
|
| 146 | + $rules = $this->getValidationRules($request); |
|
| 147 | + $errors = glsr(Validator::class)->validate($request, $rules); |
|
| 148 | + if (empty($errors)) { |
|
| 149 | + return true; |
|
| 150 | + } |
|
| 151 | + $this->setSessionValues('errors', $errors); |
|
| 152 | + $this->setSessionValues('values', $request); |
|
| 153 | + return false; |
|
| 154 | + } |
|
| 155 | 155 | |
| 156 | - /** |
|
| 157 | - * @param string $type |
|
| 158 | - * @param mixed $value |
|
| 159 | - * @param string $loggedMessage |
|
| 160 | - * @return void |
|
| 161 | - */ |
|
| 162 | - protected function setSessionValues($type, $value, $loggedMessage = '') |
|
| 163 | - { |
|
| 164 | - glsr(Session::class)->set($this->form_id.$type, $value); |
|
| 165 | - if (!empty($loggedMessage)) { |
|
| 166 | - glsr_log()->warning($loggedMessage)->debug($this->request); |
|
| 167 | - } |
|
| 168 | - } |
|
| 156 | + /** |
|
| 157 | + * @param string $type |
|
| 158 | + * @param mixed $value |
|
| 159 | + * @param string $loggedMessage |
|
| 160 | + * @return void |
|
| 161 | + */ |
|
| 162 | + protected function setSessionValues($type, $value, $loggedMessage = '') |
|
| 163 | + { |
|
| 164 | + glsr(Session::class)->set($this->form_id.$type, $value); |
|
| 165 | + if (!empty($loggedMessage)) { |
|
| 166 | + glsr_log()->warning($loggedMessage)->debug($this->request); |
|
| 167 | + } |
|
| 168 | + } |
|
| 169 | 169 | |
| 170 | - /** |
|
| 171 | - * @return void |
|
| 172 | - */ |
|
| 173 | - protected function validateAkismet() |
|
| 174 | - { |
|
| 175 | - if (!empty($this->error)) { |
|
| 176 | - return; |
|
| 177 | - } |
|
| 178 | - if (!glsr(Akismet::class)->isSpam($this->request)) { |
|
| 179 | - return; |
|
| 180 | - } |
|
| 181 | - $this->setSessionValues('errors', [], 'Akismet caught a spam submission (consider adding the IP address to the blacklist):'); |
|
| 182 | - $this->error = __('This review has been flagged as possible spam and cannot be submitted.', 'site-reviews'); |
|
| 183 | - } |
|
| 170 | + /** |
|
| 171 | + * @return void |
|
| 172 | + */ |
|
| 173 | + protected function validateAkismet() |
|
| 174 | + { |
|
| 175 | + if (!empty($this->error)) { |
|
| 176 | + return; |
|
| 177 | + } |
|
| 178 | + if (!glsr(Akismet::class)->isSpam($this->request)) { |
|
| 179 | + return; |
|
| 180 | + } |
|
| 181 | + $this->setSessionValues('errors', [], 'Akismet caught a spam submission (consider adding the IP address to the blacklist):'); |
|
| 182 | + $this->error = __('This review has been flagged as possible spam and cannot be submitted.', 'site-reviews'); |
|
| 183 | + } |
|
| 184 | 184 | |
| 185 | - /** |
|
| 186 | - * @return void |
|
| 187 | - */ |
|
| 188 | - protected function validateBlacklist() |
|
| 189 | - { |
|
| 190 | - if (!empty($this->error)) { |
|
| 191 | - return; |
|
| 192 | - } |
|
| 193 | - if (!glsr(Blacklist::class)->isBlacklisted($this->request)) { |
|
| 194 | - return; |
|
| 195 | - } |
|
| 196 | - $blacklistAction = $this->getOption('settings.submissions.blacklist.action'); |
|
| 197 | - if ('reject' == $blacklistAction) { |
|
| 198 | - $this->setSessionValues('errors', [], 'Blacklisted submission detected:'); |
|
| 199 | - $this->error = __('Your review cannot be submitted at this time.', 'site-reviews'); |
|
| 200 | - return; |
|
| 201 | - } |
|
| 202 | - $this->request['blacklisted'] = true; |
|
| 203 | - } |
|
| 185 | + /** |
|
| 186 | + * @return void |
|
| 187 | + */ |
|
| 188 | + protected function validateBlacklist() |
|
| 189 | + { |
|
| 190 | + if (!empty($this->error)) { |
|
| 191 | + return; |
|
| 192 | + } |
|
| 193 | + if (!glsr(Blacklist::class)->isBlacklisted($this->request)) { |
|
| 194 | + return; |
|
| 195 | + } |
|
| 196 | + $blacklistAction = $this->getOption('settings.submissions.blacklist.action'); |
|
| 197 | + if ('reject' == $blacklistAction) { |
|
| 198 | + $this->setSessionValues('errors', [], 'Blacklisted submission detected:'); |
|
| 199 | + $this->error = __('Your review cannot be submitted at this time.', 'site-reviews'); |
|
| 200 | + return; |
|
| 201 | + } |
|
| 202 | + $this->request['blacklisted'] = true; |
|
| 203 | + } |
|
| 204 | 204 | |
| 205 | - /** |
|
| 206 | - * @return void |
|
| 207 | - */ |
|
| 208 | - protected function validateCustom() |
|
| 209 | - { |
|
| 210 | - if (!empty($this->error)) { |
|
| 211 | - return; |
|
| 212 | - } |
|
| 213 | - $validated = apply_filters('site-reviews/validate/custom', true, $this->request); |
|
| 214 | - if (true === $validated) { |
|
| 215 | - return; |
|
| 216 | - } |
|
| 217 | - $this->setSessionValues('errors', []); |
|
| 218 | - $this->setSessionValues('values', $this->request); |
|
| 219 | - $this->error = is_string($validated) |
|
| 220 | - ? $validated |
|
| 221 | - : __('The review submission failed. Please notify the site administrator.', 'site-reviews'); |
|
| 222 | - } |
|
| 205 | + /** |
|
| 206 | + * @return void |
|
| 207 | + */ |
|
| 208 | + protected function validateCustom() |
|
| 209 | + { |
|
| 210 | + if (!empty($this->error)) { |
|
| 211 | + return; |
|
| 212 | + } |
|
| 213 | + $validated = apply_filters('site-reviews/validate/custom', true, $this->request); |
|
| 214 | + if (true === $validated) { |
|
| 215 | + return; |
|
| 216 | + } |
|
| 217 | + $this->setSessionValues('errors', []); |
|
| 218 | + $this->setSessionValues('values', $this->request); |
|
| 219 | + $this->error = is_string($validated) |
|
| 220 | + ? $validated |
|
| 221 | + : __('The review submission failed. Please notify the site administrator.', 'site-reviews'); |
|
| 222 | + } |
|
| 223 | 223 | |
| 224 | - /** |
|
| 225 | - * @return void |
|
| 226 | - */ |
|
| 227 | - protected function validateHoneyPot() |
|
| 228 | - { |
|
| 229 | - if (!empty($this->error)) { |
|
| 230 | - return; |
|
| 231 | - } |
|
| 232 | - if (empty($this->request['gotcha'])) { |
|
| 233 | - return; |
|
| 234 | - } |
|
| 235 | - $this->setSessionValues('errors', [], 'The Honeypot caught a bad submission:'); |
|
| 236 | - $this->error = __('The review submission failed. Please notify the site administrator.', 'site-reviews'); |
|
| 237 | - } |
|
| 224 | + /** |
|
| 225 | + * @return void |
|
| 226 | + */ |
|
| 227 | + protected function validateHoneyPot() |
|
| 228 | + { |
|
| 229 | + if (!empty($this->error)) { |
|
| 230 | + return; |
|
| 231 | + } |
|
| 232 | + if (empty($this->request['gotcha'])) { |
|
| 233 | + return; |
|
| 234 | + } |
|
| 235 | + $this->setSessionValues('errors', [], 'The Honeypot caught a bad submission:'); |
|
| 236 | + $this->error = __('The review submission failed. Please notify the site administrator.', 'site-reviews'); |
|
| 237 | + } |
|
| 238 | 238 | |
| 239 | - /** |
|
| 240 | - * @return void |
|
| 241 | - */ |
|
| 242 | - protected function validateRecaptcha() |
|
| 243 | - { |
|
| 244 | - if (!empty($this->error)) { |
|
| 245 | - return; |
|
| 246 | - } |
|
| 247 | - $status = $this->getRecaptchaStatus(); |
|
| 248 | - if (in_array($status, [static::RECAPTCHA_DISABLED, static::RECAPTCHA_VALID])) { |
|
| 249 | - return; |
|
| 250 | - } |
|
| 251 | - if ($status == static::RECAPTCHA_EMPTY) { |
|
| 252 | - $this->setSessionValues('recaptcha', 'unset'); |
|
| 253 | - $this->recaptchaIsUnset = true; |
|
| 254 | - return; |
|
| 255 | - } |
|
| 256 | - $this->setSessionValues('errors', []); |
|
| 257 | - $this->setSessionValues('recaptcha', 'reset'); |
|
| 258 | - $errors = [ |
|
| 259 | - static::RECAPTCHA_FAILED => __('The reCAPTCHA failed to load, please refresh the page and try again.', 'site-reviews'), |
|
| 260 | - static::RECAPTCHA_INVALID => __('The reCAPTCHA verification failed, please try again.', 'site-reviews'), |
|
| 261 | - ]; |
|
| 262 | - $this->error = $errors[$status]; |
|
| 263 | - } |
|
| 239 | + /** |
|
| 240 | + * @return void |
|
| 241 | + */ |
|
| 242 | + protected function validateRecaptcha() |
|
| 243 | + { |
|
| 244 | + if (!empty($this->error)) { |
|
| 245 | + return; |
|
| 246 | + } |
|
| 247 | + $status = $this->getRecaptchaStatus(); |
|
| 248 | + if (in_array($status, [static::RECAPTCHA_DISABLED, static::RECAPTCHA_VALID])) { |
|
| 249 | + return; |
|
| 250 | + } |
|
| 251 | + if ($status == static::RECAPTCHA_EMPTY) { |
|
| 252 | + $this->setSessionValues('recaptcha', 'unset'); |
|
| 253 | + $this->recaptchaIsUnset = true; |
|
| 254 | + return; |
|
| 255 | + } |
|
| 256 | + $this->setSessionValues('errors', []); |
|
| 257 | + $this->setSessionValues('recaptcha', 'reset'); |
|
| 258 | + $errors = [ |
|
| 259 | + static::RECAPTCHA_FAILED => __('The reCAPTCHA failed to load, please refresh the page and try again.', 'site-reviews'), |
|
| 260 | + static::RECAPTCHA_INVALID => __('The reCAPTCHA verification failed, please try again.', 'site-reviews'), |
|
| 261 | + ]; |
|
| 262 | + $this->error = $errors[$status]; |
|
| 263 | + } |
|
| 264 | 264 | |
| 265 | - /** |
|
| 266 | - * @return array |
|
| 267 | - */ |
|
| 268 | - protected function validateRequest(array $request) |
|
| 269 | - { |
|
| 270 | - if (!$this->isRequestValid($request)) { |
|
| 271 | - $this->error = __('Please fix the submission errors.', 'site-reviews'); |
|
| 272 | - return $request; |
|
| 273 | - } |
|
| 274 | - return array_merge(glsr(ValidateReviewDefaults::class)->defaults(), $request); |
|
| 275 | - } |
|
| 265 | + /** |
|
| 266 | + * @return array |
|
| 267 | + */ |
|
| 268 | + protected function validateRequest(array $request) |
|
| 269 | + { |
|
| 270 | + if (!$this->isRequestValid($request)) { |
|
| 271 | + $this->error = __('Please fix the submission errors.', 'site-reviews'); |
|
| 272 | + return $request; |
|
| 273 | + } |
|
| 274 | + return array_merge(glsr(ValidateReviewDefaults::class)->defaults(), $request); |
|
| 275 | + } |
|
| 276 | 276 | } |
@@ -4,206 +4,206 @@ |
||
| 4 | 4 | |
| 5 | 5 | class Rating |
| 6 | 6 | { |
| 7 | - /** |
|
| 8 | - * The more sure we are of the confidence interval (the higher the confidence level), the less |
|
| 9 | - * precise the estimation will be as the margin for error will be higher. |
|
| 10 | - * @see http://homepages.math.uic.edu/~bpower6/stat101/Confidence%20Intervals.pdf |
|
| 11 | - * @see https://www.thecalculator.co/math/Confidence-Interval-Calculator-210.html |
|
| 12 | - * @see https://www.youtube.com/watch?v=grodoLzThy4 |
|
| 13 | - * @see https://en.wikipedia.org/wiki/Standard_score |
|
| 14 | - * @var array |
|
| 15 | - */ |
|
| 16 | - const CONFIDENCE_LEVEL_Z_SCORES = [ |
|
| 17 | - 50 => 0.67449, |
|
| 18 | - 70 => 1.04, |
|
| 19 | - 75 => 1.15035, |
|
| 20 | - 80 => 1.282, |
|
| 21 | - 85 => 1.44, |
|
| 22 | - 90 => 1.64485, |
|
| 23 | - 92 => 1.75, |
|
| 24 | - 95 => 1.95996, |
|
| 25 | - 96 => 2.05, |
|
| 26 | - 97 => 2.17009, |
|
| 27 | - 98 => 2.326, |
|
| 28 | - 99 => 2.57583, |
|
| 29 | - '99.5' => 2.81, |
|
| 30 | - '99.8' => 3.08, |
|
| 31 | - '99.9' => 3.29053, |
|
| 32 | - ]; |
|
| 7 | + /** |
|
| 8 | + * The more sure we are of the confidence interval (the higher the confidence level), the less |
|
| 9 | + * precise the estimation will be as the margin for error will be higher. |
|
| 10 | + * @see http://homepages.math.uic.edu/~bpower6/stat101/Confidence%20Intervals.pdf |
|
| 11 | + * @see https://www.thecalculator.co/math/Confidence-Interval-Calculator-210.html |
|
| 12 | + * @see https://www.youtube.com/watch?v=grodoLzThy4 |
|
| 13 | + * @see https://en.wikipedia.org/wiki/Standard_score |
|
| 14 | + * @var array |
|
| 15 | + */ |
|
| 16 | + const CONFIDENCE_LEVEL_Z_SCORES = [ |
|
| 17 | + 50 => 0.67449, |
|
| 18 | + 70 => 1.04, |
|
| 19 | + 75 => 1.15035, |
|
| 20 | + 80 => 1.282, |
|
| 21 | + 85 => 1.44, |
|
| 22 | + 90 => 1.64485, |
|
| 23 | + 92 => 1.75, |
|
| 24 | + 95 => 1.95996, |
|
| 25 | + 96 => 2.05, |
|
| 26 | + 97 => 2.17009, |
|
| 27 | + 98 => 2.326, |
|
| 28 | + 99 => 2.57583, |
|
| 29 | + '99.5' => 2.81, |
|
| 30 | + '99.8' => 3.08, |
|
| 31 | + '99.9' => 3.29053, |
|
| 32 | + ]; |
|
| 33 | 33 | |
| 34 | - /** |
|
| 35 | - * @var int |
|
| 36 | - */ |
|
| 37 | - const MAX_RATING = 5; |
|
| 34 | + /** |
|
| 35 | + * @var int |
|
| 36 | + */ |
|
| 37 | + const MAX_RATING = 5; |
|
| 38 | 38 | |
| 39 | - /** |
|
| 40 | - * @var int |
|
| 41 | - */ |
|
| 42 | - const MIN_RATING = 1; |
|
| 39 | + /** |
|
| 40 | + * @var int |
|
| 41 | + */ |
|
| 42 | + const MIN_RATING = 1; |
|
| 43 | 43 | |
| 44 | - /** |
|
| 45 | - * @param int $roundBy |
|
| 46 | - * @return float |
|
| 47 | - */ |
|
| 48 | - public function getAverage(array $ratingCounts, $roundBy = 1) |
|
| 49 | - { |
|
| 50 | - $average = array_sum($ratingCounts); |
|
| 51 | - if ($average > 0) { |
|
| 52 | - $average = round($this->getTotalSum($ratingCounts) / $average, intval($roundBy)); |
|
| 53 | - } |
|
| 54 | - return floatval(apply_filters('site-reviews/rating/average', $average, $ratingCounts)); |
|
| 55 | - } |
|
| 44 | + /** |
|
| 45 | + * @param int $roundBy |
|
| 46 | + * @return float |
|
| 47 | + */ |
|
| 48 | + public function getAverage(array $ratingCounts, $roundBy = 1) |
|
| 49 | + { |
|
| 50 | + $average = array_sum($ratingCounts); |
|
| 51 | + if ($average > 0) { |
|
| 52 | + $average = round($this->getTotalSum($ratingCounts) / $average, intval($roundBy)); |
|
| 53 | + } |
|
| 54 | + return floatval(apply_filters('site-reviews/rating/average', $average, $ratingCounts)); |
|
| 55 | + } |
|
| 56 | 56 | |
| 57 | - /** |
|
| 58 | - * Get the lower bound for up/down ratings |
|
| 59 | - * Method receives an up/down ratings array: [1, -1, -1, 1, 1, -1]. |
|
| 60 | - * @see http://www.evanmiller.org/how-not-to-sort-by-average-rating.html |
|
| 61 | - * @see https://news.ycombinator.com/item?id=10481507 |
|
| 62 | - * @see https://dataorigami.net/blogs/napkin-folding/79030467-an-algorithm-to-sort-top-comments |
|
| 63 | - * @see http://julesjacobs.github.io/2015/08/17/bayesian-scoring-of-ratings.html |
|
| 64 | - * @param int $confidencePercentage |
|
| 65 | - * @return int|float |
|
| 66 | - */ |
|
| 67 | - public function getLowerBound(array $upDownCounts = [0, 0], $confidencePercentage = 95) |
|
| 68 | - { |
|
| 69 | - $numRatings = array_sum($upDownCounts); |
|
| 70 | - if ($numRatings < 1) { |
|
| 71 | - return 0; |
|
| 72 | - } |
|
| 73 | - $z = static::CONFIDENCE_LEVEL_Z_SCORES[$confidencePercentage]; |
|
| 74 | - $phat = 1 * $upDownCounts[1] / $numRatings; |
|
| 75 | - return ($phat + $z * $z / (2 * $numRatings) - $z * sqrt(($phat * (1 - $phat) + $z * $z / (4 * $numRatings)) / $numRatings)) / (1 + $z * $z / $numRatings); |
|
| 76 | - } |
|
| 57 | + /** |
|
| 58 | + * Get the lower bound for up/down ratings |
|
| 59 | + * Method receives an up/down ratings array: [1, -1, -1, 1, 1, -1]. |
|
| 60 | + * @see http://www.evanmiller.org/how-not-to-sort-by-average-rating.html |
|
| 61 | + * @see https://news.ycombinator.com/item?id=10481507 |
|
| 62 | + * @see https://dataorigami.net/blogs/napkin-folding/79030467-an-algorithm-to-sort-top-comments |
|
| 63 | + * @see http://julesjacobs.github.io/2015/08/17/bayesian-scoring-of-ratings.html |
|
| 64 | + * @param int $confidencePercentage |
|
| 65 | + * @return int|float |
|
| 66 | + */ |
|
| 67 | + public function getLowerBound(array $upDownCounts = [0, 0], $confidencePercentage = 95) |
|
| 68 | + { |
|
| 69 | + $numRatings = array_sum($upDownCounts); |
|
| 70 | + if ($numRatings < 1) { |
|
| 71 | + return 0; |
|
| 72 | + } |
|
| 73 | + $z = static::CONFIDENCE_LEVEL_Z_SCORES[$confidencePercentage]; |
|
| 74 | + $phat = 1 * $upDownCounts[1] / $numRatings; |
|
| 75 | + return ($phat + $z * $z / (2 * $numRatings) - $z * sqrt(($phat * (1 - $phat) + $z * $z / (4 * $numRatings)) / $numRatings)) / (1 + $z * $z / $numRatings); |
|
| 76 | + } |
|
| 77 | 77 | |
| 78 | - /** |
|
| 79 | - * @return int|float |
|
| 80 | - */ |
|
| 81 | - public function getOverallPercentage(array $ratingCounts) |
|
| 82 | - { |
|
| 83 | - return round($this->getAverage($ratingCounts) * 100 / glsr()->constant('MAX_RATING'), 2); |
|
| 84 | - } |
|
| 78 | + /** |
|
| 79 | + * @return int|float |
|
| 80 | + */ |
|
| 81 | + public function getOverallPercentage(array $ratingCounts) |
|
| 82 | + { |
|
| 83 | + return round($this->getAverage($ratingCounts) * 100 / glsr()->constant('MAX_RATING'), 2); |
|
| 84 | + } |
|
| 85 | 85 | |
| 86 | - /** |
|
| 87 | - * @return array |
|
| 88 | - */ |
|
| 89 | - public function getPercentages(array $ratingCounts) |
|
| 90 | - { |
|
| 91 | - $total = array_sum($ratingCounts); |
|
| 92 | - foreach ($ratingCounts as $index => $count) { |
|
| 93 | - if (empty($count)) { |
|
| 94 | - continue; |
|
| 95 | - } |
|
| 96 | - $ratingCounts[$index] = $count / $total * 100; |
|
| 97 | - } |
|
| 98 | - return $this->getRoundedPercentages($ratingCounts); |
|
| 99 | - } |
|
| 86 | + /** |
|
| 87 | + * @return array |
|
| 88 | + */ |
|
| 89 | + public function getPercentages(array $ratingCounts) |
|
| 90 | + { |
|
| 91 | + $total = array_sum($ratingCounts); |
|
| 92 | + foreach ($ratingCounts as $index => $count) { |
|
| 93 | + if (empty($count)) { |
|
| 94 | + continue; |
|
| 95 | + } |
|
| 96 | + $ratingCounts[$index] = $count / $total * 100; |
|
| 97 | + } |
|
| 98 | + return $this->getRoundedPercentages($ratingCounts); |
|
| 99 | + } |
|
| 100 | 100 | |
| 101 | - /** |
|
| 102 | - * @return float |
|
| 103 | - */ |
|
| 104 | - public function getRanking(array $ratingCounts) |
|
| 105 | - { |
|
| 106 | - return floatval(apply_filters('site-reviews/rating/ranking', |
|
| 107 | - $this->getRankingUsingImdb($ratingCounts), |
|
| 108 | - $ratingCounts, |
|
| 109 | - $this |
|
| 110 | - )); |
|
| 111 | - } |
|
| 101 | + /** |
|
| 102 | + * @return float |
|
| 103 | + */ |
|
| 104 | + public function getRanking(array $ratingCounts) |
|
| 105 | + { |
|
| 106 | + return floatval(apply_filters('site-reviews/rating/ranking', |
|
| 107 | + $this->getRankingUsingImdb($ratingCounts), |
|
| 108 | + $ratingCounts, |
|
| 109 | + $this |
|
| 110 | + )); |
|
| 111 | + } |
|
| 112 | 112 | |
| 113 | - /** |
|
| 114 | - * Get the bayesian ranking for an array of reviews |
|
| 115 | - * This formula is the same one used by IMDB to rank their top 250 films. |
|
| 116 | - * @see https://www.xkcd.com/937/ |
|
| 117 | - * @see https://districtdatalabs.silvrback.com/computing-a-bayesian-estimate-of-star-rating-means |
|
| 118 | - * @see http://fulmicoton.com/posts/bayesian_rating/ |
|
| 119 | - * @see https://stats.stackexchange.com/questions/93974/is-there-an-equivalent-to-lower-bound-of-wilson-score-confidence-interval-for-va |
|
| 120 | - * @param int $confidencePercentage |
|
| 121 | - * @return int|float |
|
| 122 | - */ |
|
| 123 | - public function getRankingUsingImdb(array $ratingCounts, $confidencePercentage = 70) |
|
| 124 | - { |
|
| 125 | - $avgRating = $this->getAverage($ratingCounts); |
|
| 126 | - // Represents a prior (your prior opinion without data) for the average star rating. A higher prior also means a higher margin for error. |
|
| 127 | - // This could also be the average score of all items instead of a fixed value. |
|
| 128 | - $bayesMean = ($confidencePercentage / 100) * glsr()->constant('MAX_RATING'); // prior, 70% = 3.5 |
|
| 129 | - // Represents the number of ratings expected to begin observing a pattern that would put confidence in the prior. |
|
| 130 | - $bayesMinimal = 10; // confidence |
|
| 131 | - $numOfReviews = array_sum($ratingCounts); |
|
| 132 | - return $avgRating > 0 |
|
| 133 | - ? (($bayesMinimal * $bayesMean) + ($avgRating * $numOfReviews)) / ($bayesMinimal + $numOfReviews) |
|
| 134 | - : 0; |
|
| 135 | - } |
|
| 113 | + /** |
|
| 114 | + * Get the bayesian ranking for an array of reviews |
|
| 115 | + * This formula is the same one used by IMDB to rank their top 250 films. |
|
| 116 | + * @see https://www.xkcd.com/937/ |
|
| 117 | + * @see https://districtdatalabs.silvrback.com/computing-a-bayesian-estimate-of-star-rating-means |
|
| 118 | + * @see http://fulmicoton.com/posts/bayesian_rating/ |
|
| 119 | + * @see https://stats.stackexchange.com/questions/93974/is-there-an-equivalent-to-lower-bound-of-wilson-score-confidence-interval-for-va |
|
| 120 | + * @param int $confidencePercentage |
|
| 121 | + * @return int|float |
|
| 122 | + */ |
|
| 123 | + public function getRankingUsingImdb(array $ratingCounts, $confidencePercentage = 70) |
|
| 124 | + { |
|
| 125 | + $avgRating = $this->getAverage($ratingCounts); |
|
| 126 | + // Represents a prior (your prior opinion without data) for the average star rating. A higher prior also means a higher margin for error. |
|
| 127 | + // This could also be the average score of all items instead of a fixed value. |
|
| 128 | + $bayesMean = ($confidencePercentage / 100) * glsr()->constant('MAX_RATING'); // prior, 70% = 3.5 |
|
| 129 | + // Represents the number of ratings expected to begin observing a pattern that would put confidence in the prior. |
|
| 130 | + $bayesMinimal = 10; // confidence |
|
| 131 | + $numOfReviews = array_sum($ratingCounts); |
|
| 132 | + return $avgRating > 0 |
|
| 133 | + ? (($bayesMinimal * $bayesMean) + ($avgRating * $numOfReviews)) / ($bayesMinimal + $numOfReviews) |
|
| 134 | + : 0; |
|
| 135 | + } |
|
| 136 | 136 | |
| 137 | - /** |
|
| 138 | - * The quality of a 5 star rating depends not only on the average number of stars but also on |
|
| 139 | - * the number of reviews. This method calculates the bayesian ranking of a page by its number |
|
| 140 | - * of reviews and their rating. |
|
| 141 | - * @see http://www.evanmiller.org/ranking-items-with-star-ratings.html |
|
| 142 | - * @see https://stackoverflow.com/questions/1411199/what-is-a-better-way-to-sort-by-a-5-star-rating/1411268 |
|
| 143 | - * @see http://julesjacobs.github.io/2015/08/17/bayesian-scoring-of-ratings.html |
|
| 144 | - * @param int $confidencePercentage |
|
| 145 | - * @return float |
|
| 146 | - */ |
|
| 147 | - public function getRankingUsingZScores(array $ratingCounts, $confidencePercentage = 90) |
|
| 148 | - { |
|
| 149 | - $ratingCountsSum = array_sum($ratingCounts) + glsr()->constant('MAX_RATING'); |
|
| 150 | - $weight = $this->getWeight($ratingCounts, $ratingCountsSum); |
|
| 151 | - $weightPow2 = $this->getWeight($ratingCounts, $ratingCountsSum, true); |
|
| 152 | - $zScore = static::CONFIDENCE_LEVEL_Z_SCORES[$confidencePercentage]; |
|
| 153 | - return $weight - $zScore * sqrt(($weightPow2 - pow($weight, 2)) / ($ratingCountsSum + 1)); |
|
| 154 | - } |
|
| 137 | + /** |
|
| 138 | + * The quality of a 5 star rating depends not only on the average number of stars but also on |
|
| 139 | + * the number of reviews. This method calculates the bayesian ranking of a page by its number |
|
| 140 | + * of reviews and their rating. |
|
| 141 | + * @see http://www.evanmiller.org/ranking-items-with-star-ratings.html |
|
| 142 | + * @see https://stackoverflow.com/questions/1411199/what-is-a-better-way-to-sort-by-a-5-star-rating/1411268 |
|
| 143 | + * @see http://julesjacobs.github.io/2015/08/17/bayesian-scoring-of-ratings.html |
|
| 144 | + * @param int $confidencePercentage |
|
| 145 | + * @return float |
|
| 146 | + */ |
|
| 147 | + public function getRankingUsingZScores(array $ratingCounts, $confidencePercentage = 90) |
|
| 148 | + { |
|
| 149 | + $ratingCountsSum = array_sum($ratingCounts) + glsr()->constant('MAX_RATING'); |
|
| 150 | + $weight = $this->getWeight($ratingCounts, $ratingCountsSum); |
|
| 151 | + $weightPow2 = $this->getWeight($ratingCounts, $ratingCountsSum, true); |
|
| 152 | + $zScore = static::CONFIDENCE_LEVEL_Z_SCORES[$confidencePercentage]; |
|
| 153 | + return $weight - $zScore * sqrt(($weightPow2 - pow($weight, 2)) / ($ratingCountsSum + 1)); |
|
| 154 | + } |
|
| 155 | 155 | |
| 156 | - /** |
|
| 157 | - * @param int $target |
|
| 158 | - * @return array |
|
| 159 | - */ |
|
| 160 | - protected function getRoundedPercentages(array $percentages, $totalPercent = 100) |
|
| 161 | - { |
|
| 162 | - array_walk($percentages, function (&$percent, $index) { |
|
| 163 | - $percent = [ |
|
| 164 | - 'index' => $index, |
|
| 165 | - 'percent' => floor($percent), |
|
| 166 | - 'remainder' => fmod($percent, 1), |
|
| 167 | - ]; |
|
| 168 | - }); |
|
| 169 | - $indexes = glsr_array_column($percentages, 'index'); |
|
| 170 | - $remainders = glsr_array_column($percentages, 'remainder'); |
|
| 171 | - array_multisort($remainders, SORT_DESC, SORT_STRING, $indexes, SORT_DESC, $percentages); |
|
| 172 | - $i = 0; |
|
| 173 | - if (array_sum(glsr_array_column($percentages, 'percent')) > 0) { |
|
| 174 | - while (array_sum(glsr_array_column($percentages, 'percent')) < $totalPercent) { |
|
| 175 | - ++$percentages[$i]['percent']; |
|
| 176 | - ++$i; |
|
| 177 | - } |
|
| 178 | - } |
|
| 179 | - array_multisort($indexes, SORT_DESC, $percentages); |
|
| 180 | - return array_combine($indexes, glsr_array_column($percentages, 'percent')); |
|
| 181 | - } |
|
| 156 | + /** |
|
| 157 | + * @param int $target |
|
| 158 | + * @return array |
|
| 159 | + */ |
|
| 160 | + protected function getRoundedPercentages(array $percentages, $totalPercent = 100) |
|
| 161 | + { |
|
| 162 | + array_walk($percentages, function (&$percent, $index) { |
|
| 163 | + $percent = [ |
|
| 164 | + 'index' => $index, |
|
| 165 | + 'percent' => floor($percent), |
|
| 166 | + 'remainder' => fmod($percent, 1), |
|
| 167 | + ]; |
|
| 168 | + }); |
|
| 169 | + $indexes = glsr_array_column($percentages, 'index'); |
|
| 170 | + $remainders = glsr_array_column($percentages, 'remainder'); |
|
| 171 | + array_multisort($remainders, SORT_DESC, SORT_STRING, $indexes, SORT_DESC, $percentages); |
|
| 172 | + $i = 0; |
|
| 173 | + if (array_sum(glsr_array_column($percentages, 'percent')) > 0) { |
|
| 174 | + while (array_sum(glsr_array_column($percentages, 'percent')) < $totalPercent) { |
|
| 175 | + ++$percentages[$i]['percent']; |
|
| 176 | + ++$i; |
|
| 177 | + } |
|
| 178 | + } |
|
| 179 | + array_multisort($indexes, SORT_DESC, $percentages); |
|
| 180 | + return array_combine($indexes, glsr_array_column($percentages, 'percent')); |
|
| 181 | + } |
|
| 182 | 182 | |
| 183 | - /** |
|
| 184 | - * @return int |
|
| 185 | - */ |
|
| 186 | - protected function getTotalSum(array $ratingCounts) |
|
| 187 | - { |
|
| 188 | - return array_reduce(array_keys($ratingCounts), function ($carry, $index) use ($ratingCounts) { |
|
| 189 | - return $carry + ($index * $ratingCounts[$index]); |
|
| 190 | - }); |
|
| 191 | - } |
|
| 183 | + /** |
|
| 184 | + * @return int |
|
| 185 | + */ |
|
| 186 | + protected function getTotalSum(array $ratingCounts) |
|
| 187 | + { |
|
| 188 | + return array_reduce(array_keys($ratingCounts), function ($carry, $index) use ($ratingCounts) { |
|
| 189 | + return $carry + ($index * $ratingCounts[$index]); |
|
| 190 | + }); |
|
| 191 | + } |
|
| 192 | 192 | |
| 193 | - /** |
|
| 194 | - * @param int|float $ratingCountsSum |
|
| 195 | - * @param bool $powerOf2 |
|
| 196 | - * @return float |
|
| 197 | - */ |
|
| 198 | - protected function getWeight(array $ratingCounts, $ratingCountsSum, $powerOf2 = false) |
|
| 199 | - { |
|
| 200 | - return array_reduce(array_keys($ratingCounts), |
|
| 201 | - function ($count, $rating) use ($ratingCounts, $ratingCountsSum, $powerOf2) { |
|
| 202 | - $ratingLevel = $powerOf2 |
|
| 203 | - ? pow($rating, 2) |
|
| 204 | - : $rating; |
|
| 205 | - return $count + ($ratingLevel * ($ratingCounts[$rating] + 1)) / $ratingCountsSum; |
|
| 206 | - } |
|
| 207 | - ); |
|
| 208 | - } |
|
| 193 | + /** |
|
| 194 | + * @param int|float $ratingCountsSum |
|
| 195 | + * @param bool $powerOf2 |
|
| 196 | + * @return float |
|
| 197 | + */ |
|
| 198 | + protected function getWeight(array $ratingCounts, $ratingCountsSum, $powerOf2 = false) |
|
| 199 | + { |
|
| 200 | + return array_reduce(array_keys($ratingCounts), |
|
| 201 | + function ($count, $rating) use ($ratingCounts, $ratingCountsSum, $powerOf2) { |
|
| 202 | + $ratingLevel = $powerOf2 |
|
| 203 | + ? pow($rating, 2) |
|
| 204 | + : $rating; |
|
| 205 | + return $count + ($ratingLevel * ($ratingCounts[$rating] + 1)) / $ratingCountsSum; |
|
| 206 | + } |
|
| 207 | + ); |
|
| 208 | + } |
|
| 209 | 209 | } |
@@ -7,283 +7,283 @@ |
||
| 7 | 7 | |
| 8 | 8 | final class Application extends Container |
| 9 | 9 | { |
| 10 | - const CAPABILITY = 'edit_others_posts'; |
|
| 11 | - const CRON_EVENT = 'site-reviews/schedule/session/purge'; |
|
| 12 | - const ID = 'site-reviews'; |
|
| 13 | - const PAGED_QUERY_VAR = 'reviews-page'; |
|
| 14 | - const POST_TYPE = 'site-review'; |
|
| 15 | - const PREFIX = 'glsr_'; |
|
| 16 | - const TAXONOMY = 'site-review-category'; |
|
| 10 | + const CAPABILITY = 'edit_others_posts'; |
|
| 11 | + const CRON_EVENT = 'site-reviews/schedule/session/purge'; |
|
| 12 | + const ID = 'site-reviews'; |
|
| 13 | + const PAGED_QUERY_VAR = 'reviews-page'; |
|
| 14 | + const POST_TYPE = 'site-review'; |
|
| 15 | + const PREFIX = 'glsr_'; |
|
| 16 | + const TAXONOMY = 'site-review-category'; |
|
| 17 | 17 | |
| 18 | - public $defaults; |
|
| 19 | - public $deprecated = []; |
|
| 20 | - public $file; |
|
| 21 | - public $languages; |
|
| 22 | - public $mceShortcodes = []; //defined elsewhere |
|
| 23 | - public $name; |
|
| 24 | - public $reviewTypes; |
|
| 25 | - public $schemas = []; //defined elsewhere |
|
| 26 | - public $version; |
|
| 18 | + public $defaults; |
|
| 19 | + public $deprecated = []; |
|
| 20 | + public $file; |
|
| 21 | + public $languages; |
|
| 22 | + public $mceShortcodes = []; //defined elsewhere |
|
| 23 | + public $name; |
|
| 24 | + public $reviewTypes; |
|
| 25 | + public $schemas = []; //defined elsewhere |
|
| 26 | + public $version; |
|
| 27 | 27 | |
| 28 | - public function __construct() |
|
| 29 | - { |
|
| 30 | - static::$instance = $this; |
|
| 31 | - $this->file = realpath(trailingslashit(dirname(__DIR__)).static::ID.'.php'); |
|
| 32 | - $plugin = get_file_data($this->file, [ |
|
| 33 | - 'languages' => 'Domain Path', |
|
| 34 | - 'name' => 'Plugin Name', |
|
| 35 | - 'version' => 'Version', |
|
| 36 | - ], 'plugin'); |
|
| 37 | - array_walk($plugin, function ($value, $key) { |
|
| 38 | - $this->$key = $value; |
|
| 39 | - }); |
|
| 40 | - } |
|
| 28 | + public function __construct() |
|
| 29 | + { |
|
| 30 | + static::$instance = $this; |
|
| 31 | + $this->file = realpath(trailingslashit(dirname(__DIR__)).static::ID.'.php'); |
|
| 32 | + $plugin = get_file_data($this->file, [ |
|
| 33 | + 'languages' => 'Domain Path', |
|
| 34 | + 'name' => 'Plugin Name', |
|
| 35 | + 'version' => 'Version', |
|
| 36 | + ], 'plugin'); |
|
| 37 | + array_walk($plugin, function ($value, $key) { |
|
| 38 | + $this->$key = $value; |
|
| 39 | + }); |
|
| 40 | + } |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * @return void |
|
| 44 | - */ |
|
| 45 | - public function activate() |
|
| 46 | - { |
|
| 47 | - $this->make(DefaultsManager::class)->set(); |
|
| 48 | - $this->scheduleCronJob(); |
|
| 49 | - $this->upgrade(); |
|
| 50 | - } |
|
| 42 | + /** |
|
| 43 | + * @return void |
|
| 44 | + */ |
|
| 45 | + public function activate() |
|
| 46 | + { |
|
| 47 | + $this->make(DefaultsManager::class)->set(); |
|
| 48 | + $this->scheduleCronJob(); |
|
| 49 | + $this->upgrade(); |
|
| 50 | + } |
|
| 51 | 51 | |
| 52 | - /** |
|
| 53 | - * @return void |
|
| 54 | - */ |
|
| 55 | - public function catchFatalError() |
|
| 56 | - { |
|
| 57 | - $error = error_get_last(); |
|
| 58 | - if (E_ERROR !== $error['type'] || false === strpos($error['message'], $this->path())) { |
|
| 59 | - return; |
|
| 60 | - } |
|
| 61 | - glsr_log()->error($error['message']); |
|
| 62 | - } |
|
| 52 | + /** |
|
| 53 | + * @return void |
|
| 54 | + */ |
|
| 55 | + public function catchFatalError() |
|
| 56 | + { |
|
| 57 | + $error = error_get_last(); |
|
| 58 | + if (E_ERROR !== $error['type'] || false === strpos($error['message'], $this->path())) { |
|
| 59 | + return; |
|
| 60 | + } |
|
| 61 | + glsr_log()->error($error['message']); |
|
| 62 | + } |
|
| 63 | 63 | |
| 64 | - /** |
|
| 65 | - * @param string $name |
|
| 66 | - * @return array |
|
| 67 | - */ |
|
| 68 | - public function config($name) |
|
| 69 | - { |
|
| 70 | - $configFile = $this->path('config/'.$name.'.php'); |
|
| 71 | - $config = file_exists($configFile) |
|
| 72 | - ? include $configFile |
|
| 73 | - : []; |
|
| 74 | - return apply_filters('site-reviews/config/'.$name, $config); |
|
| 75 | - } |
|
| 64 | + /** |
|
| 65 | + * @param string $name |
|
| 66 | + * @return array |
|
| 67 | + */ |
|
| 68 | + public function config($name) |
|
| 69 | + { |
|
| 70 | + $configFile = $this->path('config/'.$name.'.php'); |
|
| 71 | + $config = file_exists($configFile) |
|
| 72 | + ? include $configFile |
|
| 73 | + : []; |
|
| 74 | + return apply_filters('site-reviews/config/'.$name, $config); |
|
| 75 | + } |
|
| 76 | 76 | |
| 77 | - /** |
|
| 78 | - * @param string $property |
|
| 79 | - * @return string |
|
| 80 | - */ |
|
| 81 | - public function constant($property, $className = 'static') |
|
| 82 | - { |
|
| 83 | - $constant = $className.'::'.$property; |
|
| 84 | - return defined($constant) |
|
| 85 | - ? apply_filters('site-reviews/const/'.$property, constant($constant)) |
|
| 86 | - : ''; |
|
| 87 | - } |
|
| 77 | + /** |
|
| 78 | + * @param string $property |
|
| 79 | + * @return string |
|
| 80 | + */ |
|
| 81 | + public function constant($property, $className = 'static') |
|
| 82 | + { |
|
| 83 | + $constant = $className.'::'.$property; |
|
| 84 | + return defined($constant) |
|
| 85 | + ? apply_filters('site-reviews/const/'.$property, constant($constant)) |
|
| 86 | + : ''; |
|
| 87 | + } |
|
| 88 | 88 | |
| 89 | - /** |
|
| 90 | - * @return void |
|
| 91 | - */ |
|
| 92 | - public function deactivate() |
|
| 93 | - { |
|
| 94 | - $this->unscheduleCronJob(); |
|
| 95 | - } |
|
| 89 | + /** |
|
| 90 | + * @return void |
|
| 91 | + */ |
|
| 92 | + public function deactivate() |
|
| 93 | + { |
|
| 94 | + $this->unscheduleCronJob(); |
|
| 95 | + } |
|
| 96 | 96 | |
| 97 | - /** |
|
| 98 | - * @param string $view |
|
| 99 | - * @return void|string |
|
| 100 | - */ |
|
| 101 | - public function file($view) |
|
| 102 | - { |
|
| 103 | - $view .= '.php'; |
|
| 104 | - $filePaths = []; |
|
| 105 | - if (glsr(Helper::class)->startsWith('templates/', $view)) { |
|
| 106 | - $filePaths[] = $this->themePath(glsr(Helper::class)->removePrefix('templates/', $view)); |
|
| 107 | - } |
|
| 108 | - $filePaths[] = $this->path($view); |
|
| 109 | - $filePaths[] = $this->path('views/'.$view); |
|
| 110 | - foreach ($filePaths as $file) { |
|
| 111 | - if (!file_exists($file)) { |
|
| 112 | - continue; |
|
| 113 | - } |
|
| 114 | - return $file; |
|
| 115 | - } |
|
| 116 | - } |
|
| 97 | + /** |
|
| 98 | + * @param string $view |
|
| 99 | + * @return void|string |
|
| 100 | + */ |
|
| 101 | + public function file($view) |
|
| 102 | + { |
|
| 103 | + $view .= '.php'; |
|
| 104 | + $filePaths = []; |
|
| 105 | + if (glsr(Helper::class)->startsWith('templates/', $view)) { |
|
| 106 | + $filePaths[] = $this->themePath(glsr(Helper::class)->removePrefix('templates/', $view)); |
|
| 107 | + } |
|
| 108 | + $filePaths[] = $this->path($view); |
|
| 109 | + $filePaths[] = $this->path('views/'.$view); |
|
| 110 | + foreach ($filePaths as $file) { |
|
| 111 | + if (!file_exists($file)) { |
|
| 112 | + continue; |
|
| 113 | + } |
|
| 114 | + return $file; |
|
| 115 | + } |
|
| 116 | + } |
|
| 117 | 117 | |
| 118 | - /** |
|
| 119 | - * @return array |
|
| 120 | - */ |
|
| 121 | - public function getDefaults() |
|
| 122 | - { |
|
| 123 | - if (empty($this->defaults)) { |
|
| 124 | - $this->defaults = $this->make(DefaultsManager::class)->get(); |
|
| 125 | - $this->upgrade(); |
|
| 126 | - } |
|
| 127 | - return apply_filters('site-reviews/get/defaults', $this->defaults); |
|
| 128 | - } |
|
| 118 | + /** |
|
| 119 | + * @return array |
|
| 120 | + */ |
|
| 121 | + public function getDefaults() |
|
| 122 | + { |
|
| 123 | + if (empty($this->defaults)) { |
|
| 124 | + $this->defaults = $this->make(DefaultsManager::class)->get(); |
|
| 125 | + $this->upgrade(); |
|
| 126 | + } |
|
| 127 | + return apply_filters('site-reviews/get/defaults', $this->defaults); |
|
| 128 | + } |
|
| 129 | 129 | |
| 130 | - /** |
|
| 131 | - * @return bool |
|
| 132 | - */ |
|
| 133 | - public function getPermission($page = '') |
|
| 134 | - { |
|
| 135 | - $permissions = [ |
|
| 136 | - 'addons' => 'install_plugins', |
|
| 137 | - 'settings' => 'manage_options', |
|
| 138 | - ]; |
|
| 139 | - return glsr_get($permissions, $page, $this->constant('CAPABILITY')); |
|
| 140 | - } |
|
| 130 | + /** |
|
| 131 | + * @return bool |
|
| 132 | + */ |
|
| 133 | + public function getPermission($page = '') |
|
| 134 | + { |
|
| 135 | + $permissions = [ |
|
| 136 | + 'addons' => 'install_plugins', |
|
| 137 | + 'settings' => 'manage_options', |
|
| 138 | + ]; |
|
| 139 | + return glsr_get($permissions, $page, $this->constant('CAPABILITY')); |
|
| 140 | + } |
|
| 141 | 141 | |
| 142 | - /** |
|
| 143 | - * @return bool |
|
| 144 | - */ |
|
| 145 | - public function hasPermission($page = '') |
|
| 146 | - { |
|
| 147 | - $isAdmin = $this->isAdmin(); |
|
| 148 | - return !$isAdmin || ($isAdmin && current_user_can($this->getPermission($page))); |
|
| 149 | - } |
|
| 142 | + /** |
|
| 143 | + * @return bool |
|
| 144 | + */ |
|
| 145 | + public function hasPermission($page = '') |
|
| 146 | + { |
|
| 147 | + $isAdmin = $this->isAdmin(); |
|
| 148 | + return !$isAdmin || ($isAdmin && current_user_can($this->getPermission($page))); |
|
| 149 | + } |
|
| 150 | 150 | |
| 151 | - /** |
|
| 152 | - * @return void |
|
| 153 | - */ |
|
| 154 | - public function init() |
|
| 155 | - { |
|
| 156 | - $this->make(Actions::class)->run(); |
|
| 157 | - $this->make(Filters::class)->run(); |
|
| 158 | - } |
|
| 151 | + /** |
|
| 152 | + * @return void |
|
| 153 | + */ |
|
| 154 | + public function init() |
|
| 155 | + { |
|
| 156 | + $this->make(Actions::class)->run(); |
|
| 157 | + $this->make(Filters::class)->run(); |
|
| 158 | + } |
|
| 159 | 159 | |
| 160 | - /** |
|
| 161 | - * @return bool |
|
| 162 | - */ |
|
| 163 | - public function isAdmin() |
|
| 164 | - { |
|
| 165 | - return is_admin() && !wp_doing_ajax(); |
|
| 166 | - } |
|
| 160 | + /** |
|
| 161 | + * @return bool |
|
| 162 | + */ |
|
| 163 | + public function isAdmin() |
|
| 164 | + { |
|
| 165 | + return is_admin() && !wp_doing_ajax(); |
|
| 166 | + } |
|
| 167 | 167 | |
| 168 | - /** |
|
| 169 | - * @param string $file |
|
| 170 | - * @return string |
|
| 171 | - */ |
|
| 172 | - public function path($file = '', $realpath = true) |
|
| 173 | - { |
|
| 174 | - $path = plugin_dir_path($this->file); |
|
| 175 | - if (!$realpath) { |
|
| 176 | - $path = trailingslashit(WP_PLUGIN_DIR).basename(dirname($this->file)); |
|
| 177 | - } |
|
| 178 | - $path = trailingslashit($path).ltrim(trim($file), '/'); |
|
| 179 | - return apply_filters('site-reviews/path', $path, $file); |
|
| 180 | - } |
|
| 168 | + /** |
|
| 169 | + * @param string $file |
|
| 170 | + * @return string |
|
| 171 | + */ |
|
| 172 | + public function path($file = '', $realpath = true) |
|
| 173 | + { |
|
| 174 | + $path = plugin_dir_path($this->file); |
|
| 175 | + if (!$realpath) { |
|
| 176 | + $path = trailingslashit(WP_PLUGIN_DIR).basename(dirname($this->file)); |
|
| 177 | + } |
|
| 178 | + $path = trailingslashit($path).ltrim(trim($file), '/'); |
|
| 179 | + return apply_filters('site-reviews/path', $path, $file); |
|
| 180 | + } |
|
| 181 | 181 | |
| 182 | - /** |
|
| 183 | - * @return void |
|
| 184 | - */ |
|
| 185 | - public function registerAddons() |
|
| 186 | - { |
|
| 187 | - do_action('site-reviews/addon/register', $this); |
|
| 188 | - } |
|
| 182 | + /** |
|
| 183 | + * @return void |
|
| 184 | + */ |
|
| 185 | + public function registerAddons() |
|
| 186 | + { |
|
| 187 | + do_action('site-reviews/addon/register', $this); |
|
| 188 | + } |
|
| 189 | 189 | |
| 190 | - /** |
|
| 191 | - * @return void |
|
| 192 | - */ |
|
| 193 | - public function registerLanguages() |
|
| 194 | - { |
|
| 195 | - load_plugin_textdomain(static::ID, false, |
|
| 196 | - trailingslashit(plugin_basename($this->path()).'/'.$this->languages) |
|
| 197 | - ); |
|
| 198 | - } |
|
| 190 | + /** |
|
| 191 | + * @return void |
|
| 192 | + */ |
|
| 193 | + public function registerLanguages() |
|
| 194 | + { |
|
| 195 | + load_plugin_textdomain(static::ID, false, |
|
| 196 | + trailingslashit(plugin_basename($this->path()).'/'.$this->languages) |
|
| 197 | + ); |
|
| 198 | + } |
|
| 199 | 199 | |
| 200 | - /** |
|
| 201 | - * @return void |
|
| 202 | - */ |
|
| 203 | - public function registerReviewTypes() |
|
| 204 | - { |
|
| 205 | - $types = apply_filters('site-reviews/addon/types', []); |
|
| 206 | - $this->reviewTypes = wp_parse_args($types, [ |
|
| 207 | - 'local' => __('Local', 'site-reviews'), |
|
| 208 | - ]); |
|
| 209 | - } |
|
| 200 | + /** |
|
| 201 | + * @return void |
|
| 202 | + */ |
|
| 203 | + public function registerReviewTypes() |
|
| 204 | + { |
|
| 205 | + $types = apply_filters('site-reviews/addon/types', []); |
|
| 206 | + $this->reviewTypes = wp_parse_args($types, [ |
|
| 207 | + 'local' => __('Local', 'site-reviews'), |
|
| 208 | + ]); |
|
| 209 | + } |
|
| 210 | 210 | |
| 211 | - /** |
|
| 212 | - * @param string $view |
|
| 213 | - * @return void |
|
| 214 | - */ |
|
| 215 | - public function render($view, array $data = []) |
|
| 216 | - { |
|
| 217 | - $view = apply_filters('site-reviews/render/view', $view, $data); |
|
| 218 | - $file = apply_filters('site-reviews/views/file', $this->file($view), $view, $data); |
|
| 219 | - if (!file_exists($file)) { |
|
| 220 | - glsr_log()->error('File not found: '.$file); |
|
| 221 | - return; |
|
| 222 | - } |
|
| 223 | - $data = apply_filters('site-reviews/views/data', $data, $view); |
|
| 224 | - extract($data); |
|
| 225 | - include $file; |
|
| 226 | - } |
|
| 211 | + /** |
|
| 212 | + * @param string $view |
|
| 213 | + * @return void |
|
| 214 | + */ |
|
| 215 | + public function render($view, array $data = []) |
|
| 216 | + { |
|
| 217 | + $view = apply_filters('site-reviews/render/view', $view, $data); |
|
| 218 | + $file = apply_filters('site-reviews/views/file', $this->file($view), $view, $data); |
|
| 219 | + if (!file_exists($file)) { |
|
| 220 | + glsr_log()->error('File not found: '.$file); |
|
| 221 | + return; |
|
| 222 | + } |
|
| 223 | + $data = apply_filters('site-reviews/views/data', $data, $view); |
|
| 224 | + extract($data); |
|
| 225 | + include $file; |
|
| 226 | + } |
|
| 227 | 227 | |
| 228 | - /** |
|
| 229 | - * @return void |
|
| 230 | - */ |
|
| 231 | - public function scheduleCronJob() |
|
| 232 | - { |
|
| 233 | - if (wp_next_scheduled(static::CRON_EVENT)) { |
|
| 234 | - return; |
|
| 235 | - } |
|
| 236 | - wp_schedule_event(time(), 'twicedaily', static::CRON_EVENT); |
|
| 237 | - } |
|
| 228 | + /** |
|
| 229 | + * @return void |
|
| 230 | + */ |
|
| 231 | + public function scheduleCronJob() |
|
| 232 | + { |
|
| 233 | + if (wp_next_scheduled(static::CRON_EVENT)) { |
|
| 234 | + return; |
|
| 235 | + } |
|
| 236 | + wp_schedule_event(time(), 'twicedaily', static::CRON_EVENT); |
|
| 237 | + } |
|
| 238 | 238 | |
| 239 | - /** |
|
| 240 | - * @param string $file |
|
| 241 | - * @return string |
|
| 242 | - */ |
|
| 243 | - public function themePath($file = '') |
|
| 244 | - { |
|
| 245 | - return get_stylesheet_directory().'/'.static::ID.'/'.ltrim(trim($file), '/'); |
|
| 246 | - } |
|
| 239 | + /** |
|
| 240 | + * @param string $file |
|
| 241 | + * @return string |
|
| 242 | + */ |
|
| 243 | + public function themePath($file = '') |
|
| 244 | + { |
|
| 245 | + return get_stylesheet_directory().'/'.static::ID.'/'.ltrim(trim($file), '/'); |
|
| 246 | + } |
|
| 247 | 247 | |
| 248 | - /** |
|
| 249 | - * @return void |
|
| 250 | - */ |
|
| 251 | - public function unscheduleCronJob() |
|
| 252 | - { |
|
| 253 | - wp_unschedule_event(intval(wp_next_scheduled(static::CRON_EVENT)), static::CRON_EVENT); |
|
| 254 | - } |
|
| 248 | + /** |
|
| 249 | + * @return void |
|
| 250 | + */ |
|
| 251 | + public function unscheduleCronJob() |
|
| 252 | + { |
|
| 253 | + wp_unschedule_event(intval(wp_next_scheduled(static::CRON_EVENT)), static::CRON_EVENT); |
|
| 254 | + } |
|
| 255 | 255 | |
| 256 | - /** |
|
| 257 | - * @return void |
|
| 258 | - */ |
|
| 259 | - public function upgrade() |
|
| 260 | - { |
|
| 261 | - $this->make(Upgrader::class)->run(); |
|
| 262 | - } |
|
| 256 | + /** |
|
| 257 | + * @return void |
|
| 258 | + */ |
|
| 259 | + public function upgrade() |
|
| 260 | + { |
|
| 261 | + $this->make(Upgrader::class)->run(); |
|
| 262 | + } |
|
| 263 | 263 | |
| 264 | - /** |
|
| 265 | - * @param mixed $upgrader |
|
| 266 | - * @return void |
|
| 267 | - * @action upgrader_process_complete |
|
| 268 | - */ |
|
| 269 | - public function upgraded($upgrader, array $data) |
|
| 270 | - { |
|
| 271 | - if (array_key_exists('plugins', $data) |
|
| 272 | - && in_array(plugin_basename($this->file), $data['plugins']) |
|
| 273 | - && 'update' === $data['action'] |
|
| 274 | - && 'plugin' === $data['type'] |
|
| 275 | - ) { |
|
| 276 | - $this->upgrade(); |
|
| 277 | - } |
|
| 278 | - } |
|
| 264 | + /** |
|
| 265 | + * @param mixed $upgrader |
|
| 266 | + * @return void |
|
| 267 | + * @action upgrader_process_complete |
|
| 268 | + */ |
|
| 269 | + public function upgraded($upgrader, array $data) |
|
| 270 | + { |
|
| 271 | + if (array_key_exists('plugins', $data) |
|
| 272 | + && in_array(plugin_basename($this->file), $data['plugins']) |
|
| 273 | + && 'update' === $data['action'] |
|
| 274 | + && 'plugin' === $data['type'] |
|
| 275 | + ) { |
|
| 276 | + $this->upgrade(); |
|
| 277 | + } |
|
| 278 | + } |
|
| 279 | 279 | |
| 280 | - /** |
|
| 281 | - * @param string $path |
|
| 282 | - * @return string |
|
| 283 | - */ |
|
| 284 | - public function url($path = '') |
|
| 285 | - { |
|
| 286 | - $url = esc_url(plugin_dir_url($this->file).ltrim(trim($path), '/')); |
|
| 287 | - return apply_filters('site-reviews/url', $url, $path); |
|
| 288 | - } |
|
| 280 | + /** |
|
| 281 | + * @param string $path |
|
| 282 | + * @return string |
|
| 283 | + */ |
|
| 284 | + public function url($path = '') |
|
| 285 | + { |
|
| 286 | + $url = esc_url(plugin_dir_url($this->file).ltrim(trim($path), '/')); |
|
| 287 | + return apply_filters('site-reviews/url', $url, $path); |
|
| 288 | + } |
|
| 289 | 289 | } |
@@ -4,9 +4,9 @@ |
||
| 4 | 4 | |
| 5 | 5 | interface ShortcodeContract |
| 6 | 6 | { |
| 7 | - /** |
|
| 8 | - * @params string|array $atts |
|
| 9 | - * @return string |
|
| 10 | - */ |
|
| 11 | - public function buildShortcode($atts = []); |
|
| 7 | + /** |
|
| 8 | + * @params string|array $atts |
|
| 9 | + * @return string |
|
| 10 | + */ |
|
| 11 | + public function buildShortcode($atts = []); |
|
| 12 | 12 | } |
@@ -4,8 +4,8 @@ |
||
| 4 | 4 | |
| 5 | 5 | interface HooksContract |
| 6 | 6 | { |
| 7 | - /** |
|
| 8 | - * @return void |
|
| 9 | - */ |
|
| 10 | - public function run(); |
|
| 7 | + /** |
|
| 8 | + * @return void |
|
| 9 | + */ |
|
| 10 | + public function run(); |
|
| 11 | 11 | } |
@@ -4,8 +4,8 @@ |
||
| 4 | 4 | |
| 5 | 5 | interface PartialContract |
| 6 | 6 | { |
| 7 | - /** |
|
| 8 | - * @return void|string |
|
| 9 | - */ |
|
| 10 | - public function build(array $args = []); |
|
| 7 | + /** |
|
| 8 | + * @return void|string |
|
| 9 | + */ |
|
| 10 | + public function build(array $args = []); |
|
| 11 | 11 | } |
@@ -6,8 +6,8 @@ |
||
| 6 | 6 | |
| 7 | 7 | interface ProviderContract |
| 8 | 8 | { |
| 9 | - /** |
|
| 10 | - * @return void |
|
| 11 | - */ |
|
| 12 | - public function register(Application $app); |
|
| 9 | + /** |
|
| 10 | + * @return void |
|
| 11 | + */ |
|
| 12 | + public function register(Application $app); |
|
| 13 | 13 | } |