r74280 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r74279‎ | r74280 | r74281 >
Date:22:02, 4 October 2010
Author:neilk
Status:deferred (Comments)
Tags:
Comment:
multiple issues fixed relating to comment/followup revision r74262, r74263
Modified paths:
  • /branches/uploadwizard/phase3/includes/upload/SessionStash.php (modified) (history)
  • /branches/uploadwizard/phase3/includes/upload/UploadFromFileToStash.php (modified) (history)

Diff [purge]

Index: branches/uploadwizard/phase3/includes/upload/UploadFromFileToStash.php
@@ -18,7 +18,11 @@
1919 * Instead, we store it in the SessionStash, and return metadata about the file
2020 * We also create a thumbnail, which is visible only to the uploading user.
2121 *
22 - * @return {Status} result
 22+ * @param {String} $comment optional -- should not be used, here for parent class compatibility
 23+ * @param {String} $pageText: optional -- should not be used, here only for parent class compatibility
 24+ * @param {Boolean} $watch: optional -- whether to watchlist this item, should be unused, only here for parent class compatibility
 25+ * @param {User} $uer: optional -- current user, should not be used, only here for parent class compatibility
 26+ * @return {Status} $status
2327 */
2428 public function performUpload( $comment, $pageText, $watch, $user ) {
2529 $status = new Status();
@@ -31,8 +35,11 @@
3236 'mFileProps' => $this->mFileProps
3337 );
3438
 39+ if ( ! is_uploaded_file( $this->mLocalFile ) ) {
 40+ throw new MWException( 'badpath' );
 41+ }
3542 // we now change the value of the local file
36 - $this->mLocalFile = $stash->stashFile( false, $this->mTempPath, $data );
 43+ $this->mLocalFile = $stash->stashFile( $this->mTempPath, $data );
3744 $status->setResult( true, $this->mLocalFile );
3845
3946 } catch ( Exception $e ) {
Index: branches/uploadwizard/phase3/includes/upload/SessionStash.php
@@ -62,29 +62,33 @@
6363 }
6464
6565 /**
66 - * Get a file from the stash.
67 - * May throw exception if session data cannot be parsed due to schema change.
 66+ * Get a file and its metadata from the stash.
 67+ * May throw exception if session data cannot be parsed due to schema change, or key not found.
6868 * @param {Integer} $key: key
69 - * @return {null|SessionStashItem} null if no such item or item out of date, or the item
 69+ * @throws SessionStashFileNotFoundException
 70+ * @throws MWException
 71+ * @return {SessionStashItem} null if no such item or item out of date, or the item
7072 */
7173 public function getFile( $key ) {
7274 if ( !isset( $this->files[$key] ) ) {
7375 if ( !isset( $_SESSION[UploadBase::SESSION_KEYNAME][$key] ) ) {
74 - return $this->files[$key] = null;
 76+ throw new SessionStashFileNotFoundException();
7577 }
7678
77 - $stashData = $_SESSION[UploadBase::SESSION_KEYNAME][$key];
78 -
 79+ $data = $_SESSION[UploadBase::SESSION_KEYNAME][$key];
 80+wfDebug( "SESSION DATA: \n");
 81+wfDebug( print_r( $data, 1 ) );
7982 // guards against PHP class changing while session data doesn't
80 - if ($stashData['version'] !== UploadBase::SESSION_VERSION ) {
81 - return $this->files[$key] = null;
 83+ if ($data['version'] !== UploadBase::SESSION_VERSION ) {
 84+ throw new MWException( 'outdated session version' );
8285 }
83 -
84 - // The path is flattened in with the other random props so we have to dig it out.
85 - $path = $stashData['mTempPath'];
86 - $data = array_diff_key( $data, array( 'mTempPath' => true ) );
 86+
 87+ // separate the stashData into the path, and then the rest of the data
 88+ $path = $data['mTempPath'];
 89+ unset( $data['mTempPath'] );
8790
8891 $file = new SessionStashFile( $this, $this->repo, $path, $key, $data );
 92+wfDebug( "file = " . print_r( $file, 1 ) );
8993 $this->files[$key] = $file;
9094
9195 }
@@ -93,64 +97,69 @@
9498
9599 /**
96100 * Stash a file in a temp directory and record that we did this in the session, along with other parameters.
97 - * @param {Integer} $key: unique key. Used for directory hashing when storing, otherwise not important
 101+ * We store data in a flat key-val namespace because that's how UploadBase did it. This also means we have to
 102+ * ensure that the key-val pairs in $data do not overwrite other required fields.
 103+ *
98104 * @param {String} $path: path to file you want stashed
99 - * @param {Array} $data: other data you want added to the session. Do not use 'mTempPath', 'mFileProps', 'mFileSize', or 'version' as keys here
 105+ * @param {Array} $data: optional, other data you want added to the session. Do not use 'mTempPath', 'mFileProps', 'mFileSize', or 'version' as keys here
 106+ * @param {String} $key: optional, unique key for this session. Used for directory hashing when storing, otherwise not important
100107 * @return {null|SessionStashFile} file, or null on failure
101108 */
102 - public function stashFile( $key, $path, $data = array() ) {
103 - if ( !$key ) {
104 - // FIXME: Doesn't sound like a good idea if $key is to be unique
105 - // Also, why is this an integer rather than a string?
106 - $key = mt_rand( 0, 0x7fffffff );
 109+ public function stashFile( $path, $data = array(), $key = null ) {
 110+ if ( ! file_exists( $path ) ) {
 111+ throw new SessionStashBadPathException();
107112 }
 113+ $fileProps = File::getPropsFromPath( $path );
108114
 115+ // If no key was supplied, use content hash. Also has the nice property of collapsing multiple identical files
 116+ // uploaded this session, which could happen if uploads had failed.
 117+ if ( is_null( $key ) ) {
 118+ $key = $fileProps['sha1'];
 119+ }
 120+
109121 // if not already in a temporary area, put it there
110122 $status = $this->repo->storeTemp( basename($path), $path );
111123 if( !$status->isOK() ) {
112124 return null;
113125 }
114126 $stashPath = $status->value;
115 -
116 -
117 - // get props
118 - $fileProps = File::getPropsFromPath( $path );
119 - $fileSize = $fileProps['size'];
120127
121 - // standard info we always store.
 128+ // required info we always store. Must trump any other application info in data()
122129 // 'mTempPath', 'mFileSize', and 'mFileProps' are arbitrary names
123130 // chosen for compatibility with UploadBase's way of doing this.
124 - $stashData = array(
 131+ $requiredData = array(
125132 'mTempPath' => $stashPath,
126 - 'mFileSize' => $fileSize,
 133+ 'mFileSize' => $fileProps['size'],
127134 'mFileProps' => $fileProps,
128135 'version' => UploadBase::SESSION_VERSION
129136 );
130137
131 - // put extended info into the session (this changes from application to application).
132 - // UploadWizard wants different things than say FirefoggChunkedUpload.
133 - // Order is relevant: in case of a key collision, the value from $stashData wins
134 - $_SESSION[UploadBase::SESSION_KEYNAME][$key] = $data + $stashData;
 138+ // now, merge required info and extra data into the session. (The extra data changes from application to application.
 139+ // UploadWizard wants different things than say FirefoggChunkedUpload.)
 140+ $_SESSION[UploadBase::SESSION_KEYNAME][$key] = array_merge( $data, $requiredData );
135141
136142 return $this->getFile( $key );
137143 }
138144 }
139145
140146 class SessionStashFile extends UnregisteredLocalFile {
141 - public $sessionStash;
142 - public $sessionKey;
143 - public $sessionData;
 147+ private $sessionStash;
 148+ private $sessionKey;
 149+ private $sessionData;
144150 private $urlName;
145151
146152 /**
147153 * A LocalFile wrapper around a file that has been temporarily stashed, so we can do things like create thumbnails for it
148154 * Arguably UnregisteredLocalFile should be handling its own file repo but that class is a bit retarded currently
 155+ * @param {SessionStash} $stash: SessionStash, useful for obtaining config, stashing transformed files
149156 * @param {FileRepo} $repo: repository where we should find the path
150157 * @param {String} $path: path to file
 158+ * @param {String} $key: key to store the path and any stashed data under
 159+ * @param {String} $data: any other data we want stored with this file
151160 * @throws SessionStashBadPathException
152161 * @throws SessionStashFileNotFoundException
153162 */
154 - public function __construct( $stash, $repo, $path, $key, $data ) { // FIXME: document $stash, $key, $data --RK
 163+ public function __construct( $stash, $repo, $path, $key, $data ) {
155164 $this->sessionStash = $stash;
156165 $this->sessionKey = $key;
157166 $this->sessionData = $data;
@@ -269,7 +278,6 @@
270279 */
271280 public function getThumbUrl( $thumbName = false ) {
272281 $path = $this->sessionStash->getBaseUrl();
273 - $extension = $this->getExtension(); // Unused. Should this be appended to $path ? --RK
274282 if ( $thumbName !== false ) {
275283 $path .= '/' . rawurlencode( $thumbName );
276284 }
@@ -279,10 +287,9 @@
280288 /**
281289 * The basename for the URL, which we want to not be related to the filename.
282290 * Will also be used as the lookup key for a thumbnail file.
283 - * @param {Array} optional transformation parameters
284291 * @return {String} base url name, like '120px-123456.jpg'
285292 */
286 - public function getUrlName() { // FIXME: Docs say this has a parameter, but it doesn't --RK
 293+ public function getUrlName() {
287294 if ( ! $this->urlName ) {
288295 $this->urlName = $this->sessionKey . '.' . $this->getExtension();
289296 }
@@ -330,7 +337,6 @@
331338
332339 // returns a ThumbnailImage object containing the url and path. Note. NOT A FILE OBJECT.
333340 $thumb = parent::transform( $params, $flags );
334 -
335341 $key = $this->thumbName($params);
336342
337343 // remove extension, so it's stored in the session under '120px-123456'
@@ -341,7 +347,7 @@
342348 }
343349
344350 // stash the thumbnail File, and provide our caller with a way to get at its properties
345 - $stashedThumbFile = $this->sessionStash->stashFile( $key, $thumb->path );
 351+ $stashedThumbFile = $this->sessionStash->stashFile( $thumb->path, array(), $key );
346352 $thumb->thumbnailFile = $stashedThumbFile;
347353
348354 return $thumb;

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r74262Changes for 1.5.3 - split the parser function code from the ParserExtensions ...jeroendedauw17:03, 4 October 2010
r74263UploadWizard branch: Some fixes and comments for SessionStash.php. Stylize ru...catrope17:16, 4 October 2010

Comments

#Comment by Jeroen De Dauw (talk | contribs)   07:17, 5 October 2010

I don't think this is a follow up to r74262 :p

#Comment by NeilK (talk | contribs)   21:30, 5 October 2010

Sorry about that.

#Comment by Catrope (talk | contribs)   13:27, 5 October 2010
+				throw new MWException( 'badpath' );

So in SessionStash you have a SessionStashBadPath exception, but here you're using an MWException with a rather cryptic error message. That's not very consistent.

+				throw new MWException( 'outdated session version' );

Same here. Specialized exception class vs. generic exception with cryptic error message, within 10 lines of each other.

+	 * @param {String} $key: optional, unique key for this session. Used for directory hashing when storing, otherwise not important

Suggest tweaking this language. Unique key for this session suggests that each session has one key, whereas you really mean that each file has its own key that is then unique within its session.

+		if ( ! file_exists( $path ) ) {
+			throw new SessionStashBadPathException();
[...]
 		if( !$status->isOK() ) {
 			return null;

So one and the same function returns null for one error condition and throws an exception for another. That's inconsistent, and only the former behavior is documented.

-	public $sessionStash;
-	public $sessionKey;
-	public $sessionData;
+	private $sessionStash;
+	private $sessionKey;
+	private $sessionData;

Don't you need getters for at least $sessionKey/code> and $sessionData now?

#Comment by NeilK (talk | contribs)   21:54, 5 October 2010

I agree with you on the inconsistency. I'll try to standardize on using some set of standard exceptions, and translate those as needed by various callers. I don't like having to make up my own exceptions which then "escape" into the rest of the project, so I thought MWException was more correct.

As for the private vars, it turns out I don't need accessors, since all of their info is expressed in other ways (like the methods to get URLs).

#Comment by NeilK (talk | contribs)   23:58, 13 October 2010

documentation fixes, and null vs exception discrepancy fixed in r74751.

getter for sessionKey added in r74536, but still no reason (yet) to have a sessionData getter. May want this in the near future.

Status & tagging log