PublishStashedFileJob::run()   B
last analyzed

Complexity

Conditions 6
Paths 22

Size

Total Lines 101
Code Lines 61

Duplication

Lines 10
Ratio 9.9 %

Importance

Changes 0
Metric Value
cc 6
eloc 61
nc 22
nop 0
dl 10
loc 101
rs 8.1463
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Upload a file from the upload stash into the local file repo.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup Upload
22
 * @ingroup JobQueue
23
 */
24
use Wikimedia\ScopedCallback;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, ScopedCallback.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
25
26
/**
27
 * Upload a file from the upload stash into the local file repo.
28
 *
29
 * @ingroup Upload
30
 * @ingroup JobQueue
31
 */
32
class PublishStashedFileJob extends Job {
33
	public function __construct( Title $title, array $params ) {
34
		parent::__construct( 'PublishStashedFile', $title, $params );
35
		$this->removeDuplicates = true;
36
	}
37
38
	public function run() {
39
		$scope = RequestContext::importScopedSession( $this->params['session'] );
40
		$this->addTeardownCallback( function () use ( &$scope ) {
41
			ScopedCallback::consume( $scope ); // T126450
42
		} );
43
44
		$context = RequestContext::getMain();
45
		$user = $context->getUser();
46
		try {
47
			if ( !$user->isLoggedIn() ) {
48
				$this->setLastError( "Could not load the author user from session." );
49
50
				return false;
51
			}
52
53
			UploadBase::setSessionStatus(
54
				$user,
55
				$this->params['filekey'],
56
				[ 'result' => 'Poll', 'stage' => 'publish', 'status' => Status::newGood() ]
57
			);
58
59
			$upload = new UploadFromStash( $user );
60
			// @todo initialize() causes a GET, ideally we could frontload the antivirus
61
			// checks and anything else to the stash stage (which includes concatenation and
62
			// the local file is thus already there). That way, instead of GET+PUT, there could
63
			// just be a COPY operation from the stash to the public zone.
64
			$upload->initialize( $this->params['filekey'], $this->params['filename'] );
65
66
			// Check if the local file checks out (this is generally a no-op)
67
			$verification = $upload->verifyUpload();
68
			if ( $verification['status'] !== UploadBase::OK ) {
69
				$status = Status::newFatal( 'verification-error' );
70
				$status->value = [ 'verification' => $verification ];
71
				UploadBase::setSessionStatus(
72
					$user,
73
					$this->params['filekey'],
74
					[ 'result' => 'Failure', 'stage' => 'publish', 'status' => $status ]
75
				);
76
				$this->setLastError( "Could not verify upload." );
77
78
				return false;
79
			}
80
81
			// Upload the stashed file to a permanent location
82
			$status = $upload->performUpload(
83
				$this->params['comment'],
84
				$this->params['text'],
85
				$this->params['watch'],
86
				$user,
87
				isset( $this->params['tags'] ) ? $this->params['tags'] : []
88
			);
89 View Code Duplication
			if ( !$status->isGood() ) {
90
				UploadBase::setSessionStatus(
91
					$user,
92
					$this->params['filekey'],
93
					[ 'result' => 'Failure', 'stage' => 'publish', 'status' => $status ]
94
				);
95
				$this->setLastError( $status->getWikiText( false, false, 'en' ) );
96
97
				return false;
98
			}
99
100
			// Build the image info array while we have the local reference handy
101
			$apiMain = new ApiMain(); // dummy object (XXX)
102
			$imageInfo = $upload->getImageInfo( $apiMain->getResult() );
103
104
			// Cleanup any temporary local file
105
			$upload->cleanupTempFile();
106
107
			// Cache the info so the user doesn't have to wait forever to get the final info
108
			UploadBase::setSessionStatus(
109
				$user,
110
				$this->params['filekey'],
111
				[
112
					'result' => 'Success',
113
					'stage' => 'publish',
114
					'filename' => $upload->getLocalFile()->getName(),
115
					'imageinfo' => $imageInfo,
116
					'status' => Status::newGood()
117
				]
118
			);
119
		} catch ( Exception $e ) {
120
			UploadBase::setSessionStatus(
121
				$user,
122
				$this->params['filekey'],
123
				[
124
					'result' => 'Failure',
125
					'stage' => 'publish',
126
					'status' => Status::newFatal( 'api-error-publishfailed' )
127
				]
128
			);
129
			$this->setLastError( get_class( $e ) . ": " . $e->getMessage() );
130
			// To prevent potential database referential integrity issues.
131
			// See bug 32551.
132
			MWExceptionHandler::rollbackMasterChangesAndLog( $e );
133
134
			return false;
135
		}
136
137
		return true;
138
	}
139
140 View Code Duplication
	public function getDeduplicationInfo() {
141
		$info = parent::getDeduplicationInfo();
142
		if ( is_array( $info['params'] ) ) {
143
			$info['params'] = [ 'filekey' => $info['params']['filekey'] ];
144
		}
145
146
		return $info;
147
	}
148
149
	public function allowRetries() {
150
		return false;
151
	}
152
}
153