check that $wgArticle is an instance of the Article class in Skin::pageStats() per...
[lhc/web/wiklou.git] / includes / FileRevertForm.php
1 <?php
2
3 /**
4 * File reversion user interface
5 *
6 * @ingroup Media
7 * @author Rob Church <robchur@gmail.com>
8 */
9 class FileRevertForm {
10
11 protected $title = null;
12 protected $file = null;
13 protected $archiveName = '';
14 protected $timestamp = false;
15 protected $oldFile;
16
17 /**
18 * Constructor
19 *
20 * @param File $file File we're reverting
21 */
22 public function __construct( $file ) {
23 $this->title = $file->getTitle();
24 $this->file = $file;
25 }
26
27 /**
28 * Fulfil the request; shows the form or reverts the file,
29 * pending authentication, confirmation, etc.
30 */
31 public function execute() {
32 global $wgOut, $wgRequest, $wgUser, $wgLang;
33 $this->setHeaders();
34
35 if( wfReadOnly() ) {
36 $wgOut->readOnlyPage();
37 return;
38 } elseif( !$wgUser->isLoggedIn() ) {
39 $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' );
40 return;
41 } elseif( !$this->title->userCan( 'edit' ) || !$this->title->userCan( 'upload' ) ) {
42 // The standard read-only thing doesn't make a whole lot of sense
43 // here; surely it should show the image or something? -- RC
44 $article = new Article( $this->title );
45 $wgOut->readOnlyPage( $article->getContent(), true );
46 return;
47 } elseif( $wgUser->isBlocked() ) {
48 $wgOut->blockedPage();
49 return;
50 }
51
52 $this->archiveName = $wgRequest->getText( 'oldimage' );
53 $token = $wgRequest->getText( 'wpEditToken' );
54 if( !$this->isValidOldSpec() ) {
55 $wgOut->showUnexpectedValueError( 'oldimage', htmlspecialchars( $this->archiveName ) );
56 return;
57 }
58
59 if( !$this->haveOldVersion() ) {
60 $wgOut->addHTML( wfMsgExt( 'filerevert-badversion', 'parse' ) );
61 $wgOut->returnToMain( false, $this->title );
62 return;
63 }
64
65 // Perform the reversion if appropriate
66 if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $token, $this->archiveName ) ) {
67 $source = $this->file->getArchiveVirtualUrl( $this->archiveName );
68 $comment = $wgRequest->getText( 'wpComment' );
69 // TODO: Preserve file properties from database instead of reloading from file
70 $status = $this->file->upload( $source, $comment, $comment );
71 if( $status->isGood() ) {
72 $wgOut->addHTML( wfMsgExt( 'filerevert-success', 'parse', $this->title->getText(),
73 $wgLang->date( $this->getTimestamp(), true ),
74 $wgLang->time( $this->getTimestamp(), true ),
75 wfExpandUrl( $this->file->getArchiveUrl( $this->archiveName ) ) ) );
76 $wgOut->returnToMain( false, $this->title );
77 } else {
78 $wgOut->addWikiText( $status->getWikiText() );
79 }
80 return;
81 }
82
83 // Show the form
84 $this->showForm();
85 }
86
87 /**
88 * Show the confirmation form
89 */
90 protected function showForm() {
91 global $wgOut, $wgUser, $wgRequest, $wgLang, $wgContLang;
92 $timestamp = $this->getTimestamp();
93
94 $form = Xml::openElement( 'form', array( 'method' => 'post', 'action' => $this->getAction() ) );
95 $form .= Xml::hidden( 'wpEditToken', $wgUser->editToken( $this->archiveName ) );
96 $form .= '<fieldset><legend>' . wfMsgHtml( 'filerevert-legend' ) . '</legend>';
97 $form .= wfMsgExt( 'filerevert-intro', 'parse', $this->title->getText(),
98 $wgLang->date( $timestamp, true ), $wgLang->time( $timestamp, true ),
99 wfExpandUrl( $this->file->getArchiveUrl( $this->archiveName ) ) );
100 $form .= '<p>' . Xml::inputLabel( wfMsg( 'filerevert-comment' ), 'wpComment', 'wpComment',
101 60, wfMsgForContent( 'filerevert-defaultcomment',
102 $wgContLang->date( $timestamp, false, false ), $wgContLang->time( $timestamp, false, false ) ) ) . '</p>';
103 $form .= '<p>' . Xml::submitButton( wfMsg( 'filerevert-submit' ) ) . '</p>';
104 $form .= '</fieldset>';
105 $form .= '</form>';
106
107 $wgOut->addHTML( $form );
108 }
109
110 /**
111 * Set headers, titles and other bits
112 */
113 protected function setHeaders() {
114 global $wgOut, $wgUser;
115 $wgOut->setPageTitle( wfMsg( 'filerevert', $this->title->getText() ) );
116 $wgOut->setRobotPolicy( 'noindex,nofollow' );
117 $wgOut->setSubtitle( wfMsg( 'filerevert-backlink', $wgUser->getSkin()->makeKnownLinkObj( $this->title ) ) );
118 }
119
120 /**
121 * Is the provided `oldimage` value valid?
122 *
123 * @return bool
124 */
125 protected function isValidOldSpec() {
126 return strlen( $this->archiveName ) >= 16
127 && strpos( $this->archiveName, '/' ) === false
128 && strpos( $this->archiveName, '\\' ) === false;
129 }
130
131 /**
132 * Does the provided `oldimage` value correspond
133 * to an existing, local, old version of this file?
134 *
135 * @return bool
136 */
137 protected function haveOldVersion() {
138 return $this->getOldFile()->exists();
139 }
140
141 /**
142 * Prepare the form action
143 *
144 * @return string
145 */
146 protected function getAction() {
147 $q = array();
148 $q[] = 'action=revert';
149 $q[] = 'oldimage=' . urlencode( $this->archiveName );
150 return $this->title->getLocalUrl( implode( '&', $q ) );
151 }
152
153 /**
154 * Extract the timestamp of the old version
155 *
156 * @return string
157 */
158 protected function getTimestamp() {
159 if( $this->timestamp === false ) {
160 $this->timestamp = $this->getOldFile()->getTimestamp();
161 }
162 return $this->timestamp;
163 }
164
165 protected function getOldFile() {
166 if ( !isset( $this->oldFile ) ) {
167 $this->oldFile = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $this->title, $this->archiveName );
168 }
169 return $this->oldFile;
170 }
171 }