1<?php
2/**
3 * A factory for DerivedPageDataUpdater instances.
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 */
22
23namespace MediaWiki\Storage;
24
25use JobQueueGroup;
26use Language;
27use MediaWiki\Config\ServiceOptions;
28use MediaWiki\Content\IContentHandlerFactory;
29use MediaWiki\Content\Transform\ContentTransformer;
30use MediaWiki\HookContainer\HookContainer;
31use MediaWiki\Permissions\PermissionManager;
32use MediaWiki\Revision\RevisionRenderer;
33use MediaWiki\Revision\RevisionStore;
34use MediaWiki\Revision\SlotRoleRegistry;
35use MediaWiki\User\TalkPageNotificationManager;
36use MediaWiki\User\UserEditTracker;
37use MediaWiki\User\UserGroupManager;
38use MediaWiki\User\UserIdentity;
39use MediaWiki\User\UserNameUtils;
40use MessageCache;
41use ParserCache;
42use Psr\Log\LoggerInterface;
43use TitleFormatter;
44use WANObjectCache;
45use Wikimedia\Rdbms\ILBFactory;
46use WikiPage;
47
48/**
49 * A factory for PageUpdater instances.
50 *
51 * @since 1.37
52 * @ingroup Page
53 */
54class PageUpdaterFactory {
55
56	/**
57	 * Options that have to be present in the ServiceOptions object passed to the constructor.
58	 * @note must include PageUpdater::CONSTRUCTOR_OPTIONS
59	 * @internal
60	 */
61	public const CONSTRUCTOR_OPTIONS = [
62		'ArticleCountMethod',
63		'RCWatchCategoryMembership',
64		'PageCreationLog',
65		'UseAutomaticEditSummaries',
66		'ManualRevertSearchRadius',
67		'UseRCPatrol',
68	];
69
70	/** @var RevisionStore */
71	private $revisionStore;
72
73	/** @var RevisionRenderer */
74	private $revisionRenderer;
75
76	/** @var SlotRoleRegistry */
77	private $slotRoleRegistry;
78
79	/** @var ParserCache */
80	private $parserCache;
81
82	/** @var JobQueueGroup */
83	private $jobQueueGroup;
84
85	/** @var MessageCache */
86	private $messageCache;
87
88	/** @var Language */
89	private $contLang;
90
91	/** @var ILBFactory */
92	private $loadbalancerFactory;
93
94	/** @var IContentHandlerFactory */
95	private $contentHandlerFactory;
96
97	/** @var HookContainer */
98	private $hookContainer;
99
100	/** @var EditResultCache */
101	private $editResultCache;
102
103	/** @var UserNameUtils */
104	private $userNameUtils;
105
106	/** @var LoggerInterface */
107	private $logger;
108
109	/** @var ServiceOptions */
110	private $options;
111
112	/** @var UserEditTracker */
113	private $userEditTracker;
114
115	/** @var UserGroupManager */
116	private $userGroupManager;
117
118	/** @var TitleFormatter */
119	private $titleFormatter;
120
121	/** @var ContentTransformer */
122	private $contentTransformer;
123
124	/** @var PageEditStash */
125	private $pageEditStash;
126
127	/** @var TalkPageNotificationManager */
128	private $talkPageNotificationManager;
129
130	/** @var WANObjectCache */
131	private $mainWANObjectCache;
132
133	/** @var PermissionManager */
134	private $permissionManager;
135
136	/** @var string[] */
137	private $softwareTags;
138
139	/**
140	 * @param RevisionStore $revisionStore
141	 * @param RevisionRenderer $revisionRenderer
142	 * @param SlotRoleRegistry $slotRoleRegistry
143	 * @param ParserCache $parserCache
144	 * @param JobQueueGroup $jobQueueGroup
145	 * @param MessageCache $messageCache
146	 * @param Language $contLang
147	 * @param ILBFactory $loadbalancerFactory
148	 * @param IContentHandlerFactory $contentHandlerFactory
149	 * @param HookContainer $hookContainer
150	 * @param EditResultCache $editResultCache
151	 * @param UserNameUtils $userNameUtils
152	 * @param LoggerInterface $logger
153	 * @param ServiceOptions $options
154	 * @param UserEditTracker $userEditTracker
155	 * @param UserGroupManager $userGroupManager
156	 * @param TitleFormatter $titleFormatter
157	 * @param ContentTransformer $contentTransformer
158	 * @param PageEditStash $pageEditStash
159	 * @param TalkPageNotificationManager $talkPageNotificationManager
160	 * @param WANObjectCache $mainWANObjectCache
161	 * @param PermissionManager $permissionManager
162	 * @param string[] $softwareTags
163	 */
164	public function __construct(
165		RevisionStore $revisionStore,
166		RevisionRenderer $revisionRenderer,
167		SlotRoleRegistry $slotRoleRegistry,
168		ParserCache $parserCache,
169		JobQueueGroup $jobQueueGroup,
170		MessageCache $messageCache,
171		Language $contLang,
172		ILBFactory $loadbalancerFactory,
173		IContentHandlerFactory $contentHandlerFactory,
174		HookContainer $hookContainer,
175		EditResultCache $editResultCache,
176		UserNameUtils $userNameUtils,
177		LoggerInterface $logger,
178		ServiceOptions $options,
179		UserEditTracker $userEditTracker,
180		UserGroupManager $userGroupManager,
181		TitleFormatter $titleFormatter,
182		ContentTransformer $contentTransformer,
183		PageEditStash $pageEditStash,
184		TalkPageNotificationManager $talkPageNotificationManager,
185		WANObjectCache $mainWANObjectCache,
186		PermissionManager $permissionManager,
187		array $softwareTags
188	) {
189		$options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
190
191		$this->revisionStore = $revisionStore;
192		$this->revisionRenderer = $revisionRenderer;
193		$this->slotRoleRegistry = $slotRoleRegistry;
194		$this->parserCache = $parserCache;
195		$this->jobQueueGroup = $jobQueueGroup;
196		$this->messageCache = $messageCache;
197		$this->contLang = $contLang;
198		$this->loadbalancerFactory = $loadbalancerFactory;
199		$this->contentHandlerFactory = $contentHandlerFactory;
200		$this->hookContainer = $hookContainer;
201		$this->editResultCache = $editResultCache;
202		$this->userNameUtils = $userNameUtils;
203		$this->logger = $logger;
204		$this->options = $options;
205		$this->userEditTracker = $userEditTracker;
206		$this->userGroupManager = $userGroupManager;
207		$this->titleFormatter = $titleFormatter;
208		$this->contentTransformer = $contentTransformer;
209		$this->pageEditStash = $pageEditStash;
210		$this->talkPageNotificationManager = $talkPageNotificationManager;
211		$this->mainWANObjectCache = $mainWANObjectCache;
212		$this->permissionManager = $permissionManager;
213		$this->softwareTags = $softwareTags;
214	}
215
216	/**
217	 * Return a PageUpdater for building an update to a page.
218	 *
219	 * @internal For now, most code should keep using WikiPage::newPageUpdater() instead.
220	 * @note We can only start using this method everywhere when WikiPage::prepareContentForEdit()
221	 * and WikiPage::getCurrentUpdate() have been removed. For now, the WikiPage instance is
222	 * used to make the state of an ongoing edit available to hook handlers.
223	 *
224	 * @param WikiPage $page
225	 * @param UserIdentity $user
226	 *
227	 * @return PageUpdater
228	 * @since 1.37
229	 */
230	public function newPageUpdater(
231		WikiPage $page,
232		UserIdentity $user
233	): PageUpdater {
234		return $this->newPageUpdaterForDerivedPageDataUpdater(
235			$page,
236			$user,
237			$this->newDerivedPageDataUpdater( $page )
238		);
239	}
240
241	/**
242	 * Return a PageUpdater for building an update to a page, reusing the state of
243	 * an existing DerivedPageDataUpdater.
244	 *
245	 * @param WikiPage $page
246	 * @param UserIdentity $user
247	 * @param DerivedPageDataUpdater $derivedPageDataUpdater
248	 *
249	 * @return PageUpdater
250	 * @internal needed by WikiPage to back the WikiPage::newPageUpdater method.
251	 *
252	 * @since 1.37
253	 */
254	public function newPageUpdaterForDerivedPageDataUpdater(
255		WikiPage $page,
256		UserIdentity $user,
257		DerivedPageDataUpdater $derivedPageDataUpdater
258	): PageUpdater {
259		$pageUpdater = new PageUpdater(
260			$user,
261			$page, // NOTE: eventually, PageUpdater should not know about WikiPage
262			$derivedPageDataUpdater,
263			$this->loadbalancerFactory->getMainLB(),
264			$this->revisionStore,
265			$this->slotRoleRegistry,
266			$this->contentHandlerFactory,
267			$this->hookContainer,
268			$this->userEditTracker,
269			$this->userGroupManager,
270			$this->titleFormatter,
271			new ServiceOptions(
272				PageUpdater::CONSTRUCTOR_OPTIONS,
273				$this->options
274			),
275			$this->softwareTags
276		);
277
278		$pageUpdater->setUsePageCreationLog( $this->options->get( 'PageCreationLog' ) );
279		$pageUpdater->setUseAutomaticEditSummaries(
280			$this->options->get( 'UseAutomaticEditSummaries' )
281		);
282
283		return $pageUpdater;
284	}
285
286	/**
287	 * @param WikiPage $page
288	 *
289	 * @return DerivedPageDataUpdater
290	 * @internal Needed by WikiPage to back the deprecated prepareContentForEdit() method.
291	 * @note Avoid direct usage of DerivedPageDataUpdater.
292	 * @see docs/pageupdater.md for more information.
293	 */
294	public function newDerivedPageDataUpdater( WikiPage $page ): DerivedPageDataUpdater {
295		$derivedDataUpdater = new DerivedPageDataUpdater(
296			$page, // NOTE: eventually, PageUpdater should not know about WikiPage
297			$this->revisionStore,
298			$this->revisionRenderer,
299			$this->slotRoleRegistry,
300			$this->parserCache,
301			$this->jobQueueGroup,
302			$this->messageCache,
303			$this->contLang,
304			$this->loadbalancerFactory,
305			$this->contentHandlerFactory,
306			$this->hookContainer,
307			$this->editResultCache,
308			$this->userNameUtils,
309			$this->contentTransformer,
310			$this->pageEditStash,
311			$this->talkPageNotificationManager,
312			$this->mainWANObjectCache,
313			$this->permissionManager
314		);
315
316		$derivedDataUpdater->setLogger( $this->logger );
317		$derivedDataUpdater->setArticleCountMethod( $this->options->get( 'ArticleCountMethod' ) );
318		$derivedDataUpdater->setRcWatchCategoryMembership(
319			$this->options->get( 'RCWatchCategoryMembership' )
320		);
321
322		return $derivedDataUpdater;
323	}
324
325}
326