Completed
Push — master ( 03a3bb...b09e64 )
by Karsten
20:20 queued 18:20
created

getSubjectListFrom()   B

Complexity

Conditions 7
Paths 18

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 7.0071

Importance

Changes 0
Metric Value
dl 0
loc 30
ccs 18
cts 19
cp 0.9474
rs 8.5066
c 0
b 0
f 0
cc 7
nc 18
nop 1
crap 7.0071
1
<?php
2
3
namespace SCI;
4
5
use SMW\Store;
6
use SMW\DIProperty;
7
use SMW\DIWikiPage;
8
use SMW\ApplicationFactory;
9
use SMW\HashBuilder;
10
use SMW\SQLStore\CompositePropertyTableDiffIterator;
11
12
/**
13
 * If a citation text was altered then lookup related references on pages used
14
 * and schedule a dispatch update job.
15
 *
16
 * @license GNU GPL v2+
17
 * @since 1.0
18
 *
19
 * @author mwjames
20
 */
21
class CitationTextChangeUpdateJobDispatcher {
22
23
	/**
24
	 * @var Store
25
	 */
26
	private $store;
27
28
	/**
29
	 * @var ReferenceBacklinksLookup
30
	 */
31
	private $referenceBacklinksLookup;
32
33
	/**
34
	 * @var boolean
35
	 */
36
	private $enabledUpdateJobState = true;
37
38
	/**
39
	 * @since  1.0
40
	 *
41
	 * @param Store $store
42
	 * @param ReferenceBacklinksLookup $referenceBacklinksLookup
43
	 */
44 19
	public function __construct( Store $store, ReferenceBacklinksLookup $referenceBacklinksLookup ) {
45 19
		$this->store = $store;
46 19
		$this->referenceBacklinksLookup = $referenceBacklinksLookup;
47 19
	}
48
49
	/**
50
	 * @since  1.0
51
	 *
52
	 * @param boolean $enabledUpdateJobState
53
	 */
54 15
	public function setEnabledUpdateJobState( $enabledUpdateJobState ) {
55 15
		$this->enabledUpdateJobState = $enabledUpdateJobState;
56 15
	}
57
58
	/**
59
	 * @since  1.0
60
	 *
61
	 * @param DIWikiPage $subject
62
	 * @param CompositePropertyTableDiffIterator $compositePropertyTableDiffIterator
63
	 *
64
	 * @return boolean
65
	 */
66 18
	public function dispatchUpdateJobFor( DIWikiPage $subject, CompositePropertyTableDiffIterator $compositePropertyTableDiffIterator ) {
67
68 18
		if ( !$this->enabledUpdateJobState ) {
69 15
			return false;
70
		}
71
72 3
		$tableName = $this->store->getPropertyTableInfoFetcher()->findTableIdForProperty(
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMW\Store as the method getPropertyTableInfoFetcher() does only exist in the following sub-classes of SMW\Store: SMWSQLStore3, SMWSparqlStore, SMW\SPARQLStore\SPARQLStore. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
73 3
			new DIProperty( PropertyRegistry::SCI_CITE_TEXT )
74 3
		);
75
76 3
		$subjectIdList = $this->getSubjectListFrom(
77 3
			$compositePropertyTableDiffIterator->getOrderedDiffByTable( $tableName )
78 3
		);
79
80 3
		if ( ( $jobList = $this->getDispatchableTargetList( $subjectIdList ) ) === [] ) {
81 1
			return false;
82
		}
83
84 2
		$updateDispatcherJob = ApplicationFactory::getInstance()->newJobFactory()->newUpdateDispatcherJob(
85 2
			$subject->getTitle(),
86
			[
87
				'job-list' => $jobList
88 2
			]
89 2
		);
90
91 2
		$updateDispatcherJob->insert();
92
93 2
		return true;
94
	}
95
96 3
	private function getSubjectListFrom( array $orderedDiff ) {
97
98 3
		$subjectIdList = [];
99
100
		// Find out whether a cite text object was altered
101 3
		foreach ( $orderedDiff as $key => $value ) {
102
103 2
			if ( strpos( $key, 'sci_cite_text' ) === false ) {
104
				continue;
105
			}
106
107 2
			if ( !isset( $value['delete'] ) ) {
108 1
				$value['delete'] = [];
109 1
			}
110
111 2
			foreach ( $value['delete'] as $delete ) {
112 1
				$subjectIdList[] = $delete['s_id'];
113 2
			}
114
115 2
			if ( !isset( $value['insert'] ) ) {
116 1
				$value['insert'] = [];
117 1
			}
118
119 2
			foreach ( $value['insert'] as $insert ) {
120 1
				$subjectIdList[] = $insert['s_id'];
121 2
			}
122 3
		}
123
124 3
		return $subjectIdList;
125
	}
126
127 3
	private function getDispatchableTargetList( array $subjectIdList ) {
128
129 3
		if ( $subjectIdList === [] ) {
130 1
			return [];
131
		}
132
133 2
		$hashList = $this->store->getObjectIds()->getDataItemPoolHashListFor( $subjectIdList );
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class SMW\Store as the method getObjectIds() does only exist in the following sub-classes of SMW\Store: SMWSQLStore3, SMWSparqlStore, SMW\SPARQLStore\SPARQLStore. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
134 2
		$referenceBacklinks = [];
135
136 2
		foreach ( $hashList as $hash ) {
137 2
			$referenceBacklinks += $this->referenceBacklinksLookup->findReferenceBacklinksFor(
138 2
				$this->referenceBacklinksLookup->tryToFindCitationKeyFor( DIWikiPage::doUnserialize( $hash ) )
139 2
			);
140 2
		}
141
142 2
		$targetBatch = [];
143
144 2
		foreach ( $referenceBacklinks as $referenceBacklink ) {
145 2
			$targetBatch[HashBuilder::getHashIdForDiWikiPage( $referenceBacklink )] = true;
146 2
		}
147
148 2
		return $targetBatch;
149
	}
150
151
}
152