Completed
Push — master ( 33372a...46be78 )
by J.D.
03:04
created

WordPoints_Hook_Fire::hit()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 13
rs 9.4285
nc 3
cc 3
eloc 6
nop 0
1
<?php
2
3
/**
4
 * Hook fire class.
5
 *
6
 * @package wordpoints-hooks-api
7
 * @since   1.0.0
8
 */
9
10
/**
11
 * Holds the data for a hook fire.
12
 *
13
 * @since 1.0.0
14
 */
15
class WordPoints_Hook_Fire {
16
17
	/**
18
	 * The firer that is firing the hook.
19
	 *
20
	 * @since 1.0.0
21
	 *
22
	 * @var WordPoints_Hook_FirerI
23
	 */
24
	public $firer;
25
26
	/**
27
	 * The args for the event that is being fired.
28
	 *
29
	 * @since 1.0.0
30
	 *
31
	 * @var WordPoints_Hook_Event_Args
32
	 */
33
	public $event_args;
34
35
	/**
36
	 * The reaction that is being fired at.
37
	 *
38
	 * @since 1.0.0
39
	 *
40
	 * @var WordPoints_Hook_ReactionI
41
	 */
42
	public $reaction;
43
44
	/**
45
	 * The hit logger for this fire.
46
	 *
47
	 * @since 1.0.0
48
	 *
49
	 * @var WordPoints_Hook_Hit_Logger
50
	 */
51
	public $hit_logger;
52
53
	/**
54
	 * The ID of the hit (if this fire has hit).
55
	 *
56
	 * @since 1.0.0
57
	 *
58
	 * @var int
59
	 */
60
	public $hit_id;
61
62
	/**
63
	 * The hit this fire supersedes, if any.
64
	 *
65
	 * @since 1.0.0
66
	 *
67
	 * @var object
68
	 */
69
	protected $supersedes;
70
71
	/**
72
	 * @param WordPoints_Hook_Firer      $firer      The firer.
73
	 * @param WordPoints_Hook_Event_Args $event_args The event args.
74
	 * @param WordPoints_Hook_ReactionI  $reaction   The reaction.
75
	 * @param object                     $supersedes The hit superseded by this fire.
76
	 */
77
	public function __construct(
78
		WordPoints_Hook_Firer $firer,
79
		WordPoints_Hook_Event_Args $event_args,
80
		WordPoints_Hook_ReactionI $reaction,
81
		$supersedes = null
82
	) {
83
84
		$this->firer      = $firer;
85
		$this->event_args = $event_args;
86
		$this->reaction   = $reaction;
87
		$this->hit_logger = new WordPoints_Hook_Hit_Logger( $this );
88
		$this->supersedes = $supersedes;
89
	}
90
91
	/**
92
	 * Make this fire a hit.
93
	 *
94
	 * @since 1.0.0
95
	 *
96
	 * @return int|false The ID of the hit, or false if it failed to be logged.
97
	 */
98
	public function hit() {
99
100
		if ( ! $this->hit_id ) {
101
102
			$this->hit_id = $this->hit_logger->log_hit();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->hit_logger->log_hit() can also be of type false. However, the property $hit_id is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
103
104
			if ( ! $this->hit_id ) {
1 ignored issue
show
Bug Best Practice introduced by
The expression $this->hit_id of type integer|false is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
105
				return false;
106
			}
107
		}
108
109
		return $this->hit_id;
110
	}
111
112
	/**
113
	 * Get the hit being superseded by this fire.
114
	 *
115
	 * The fire will only supersede the hit if it ends up being a hit as well.
116
	 *
117
	 * @since 1.0.0
118
	 *
119
	 * @return object|false The hit being superseded by this fire, or false.
120
	 */
121
	public function get_superseded_hit() {
122
123
		if ( isset( $this->supersedes ) ) {
124
			return $this->supersedes;
125
		}
126
127
		global $wpdb;
128
129
		$hit = $wpdb->get_row(
130
			$wpdb->prepare(
131
				"
132
					SELECT *
133
					FROM `{$wpdb->wordpoints_hook_hits}`
134
					WHERE `fire_type` != %s
135
					AND `signature` = %s
136
					AND `event` = %s
137
					AND `reactor` = %s
138
					AND `reaction_type` = %s
139
					AND `reaction_id` = %d
140
					AND `superseded_by` IS NULL
141
				"
142
				, $this->firer->get_slug()
143
				, wordpoints_hooks_get_event_signature( $this->event_args )
144
				, $this->reaction->get_event_slug()
145
				, $this->reaction->get_reactor_slug()
146
				, $this->reaction->get_storage_group_slug()
147
				, $this->reaction->ID
1 ignored issue
show
Bug introduced by
Accessing ID on the interface WordPoints_Hook_ReactionI suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
148
			)
149
		);
150
151
		$this->supersedes = ( $hit ) ? $hit : false;
152
153
		return $this->supersedes;
154
	}
155
}
156
157
// EOF
158