はじまりの大地

This commit is contained in:
miteruzo
2024-07-08 03:32:47 +09:00
commit c616a96f53
7749 changed files with 478270 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
name: DokuWiki Default Tasks
on:
push:
pull_request:
schedule:
- cron: '1 18 5 * *'
jobs:
all:
uses: dokuwiki/github-action/.github/workflows/all.yml@main
+24
View File
@@ -0,0 +1,24 @@
# Create release on change to plugin.info.txt version line
# https://github.com/dokuwiki/dokuwiki/issues/3951
#
# Requires DOKUWIKI_USER and DOKUWIKI_PASS secrets be set in GitHub Actions
name: Release
on:
push:
branches:
- master
paths:
- "*.info.txt"
jobs:
release:
name: Release
# https://github.com/dokuwiki/dokuwiki/pull/3966
uses: glensc/dokuwiki/.github/workflows/plugin-release.yml@39431875f734bddc35cc6b4a899bbfdec97e8aba
secrets:
DOKUWIKI_USER: ${{ secrets.DOKUWIKI_USER }}
DOKUWIKI_PASS: ${{ secrets.DOKUWIKI_PASS }}
# vim:ts=2:sw=2:et
+339
View File
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
+35
View File
@@ -0,0 +1,35 @@
<?php
namespace dokuwiki\plugin\move;
use dokuwiki\Menu\Item\AbstractItem;
/**
* Class MenuItem
*
* Implements the Rename button for DokuWiki's menu system
*
* @package dokuwiki\plugin\move
*/
class MenuItem extends AbstractItem {
/** @var string icon file */
protected $svg = __DIR__ . '/images/rename.svg';
protected $type = "plugin_move";
public function getLinkAttributes($classprefix = 'menuitem ') {
$attr = parent::getLinkAttributes($classprefix);
if (empty($attr['class'])) {
$attr['class'] = '';
}
$attr['class'] .= ' plugin_move_page ';
return $attr;
}
/**
* Get label from plugin language file
*
* @return string
*/
public function getLabel() {
$hlp = plugin_load('action', 'move_rename');
return $hlp->getLang('renamepage');
}
}
+84
View File
@@ -0,0 +1,84 @@
<?php
namespace dokuwiki\plugin\move\test;
use DokuWikiTest;
/**
* General tests for the move plugin
*
* @group plugin_move
* @group plugins
*/
class GeneralTest extends DokuWikiTest
{
/**
* Simple test to make sure the plugin.info.txt is in correct format
*/
public function testPluginInfo(): void
{
$file = __DIR__ . '/../plugin.info.txt';
$this->assertFileExists($file);
$info = confToHash($file);
$this->assertArrayHasKey('base', $info);
$this->assertArrayHasKey('author', $info);
$this->assertArrayHasKey('email', $info);
$this->assertArrayHasKey('date', $info);
$this->assertArrayHasKey('name', $info);
$this->assertArrayHasKey('desc', $info);
$this->assertArrayHasKey('url', $info);
$this->assertEquals('move', $info['base']);
$this->assertRegExp('/^https?:\/\//', $info['url']);
$this->assertTrue(mail_isvalid($info['email']));
$this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
$this->assertTrue(false !== strtotime($info['date']));
}
/**
* Test to ensure that every conf['...'] entry in conf/default.php has a corresponding meta['...'] entry in
* conf/metadata.php.
*/
public function testPluginConf(): void
{
$conf_file = __DIR__ . '/../conf/default.php';
$meta_file = __DIR__ . '/../conf/metadata.php';
if (!file_exists($conf_file) && !file_exists($meta_file)) {
self::markTestSkipped('No config files exist -> skipping test');
}
if (file_exists($conf_file)) {
include($conf_file);
}
if (file_exists($meta_file)) {
include($meta_file);
}
$this->assertEquals(
gettype($conf),
gettype($meta),
'Both ' . DOKU_PLUGIN . 'move/conf/default.php and ' . DOKU_PLUGIN . 'move/conf/metadata.php have to exist and contain the same keys.'
);
if ($conf !== null && $meta !== null) {
foreach ($conf as $key => $value) {
$this->assertArrayHasKey(
$key,
$meta,
'Key $meta[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'move/conf/metadata.php'
);
}
foreach ($meta as $key => $value) {
$this->assertArrayHasKey(
$key,
$conf,
'Key $conf[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'move/conf/default.php'
);
}
}
}
}
@@ -0,0 +1,58 @@
<?php
/**
* Test cases for the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_affectedPagesNS_test extends DokuWikiTest {
protected $pluginsEnabled = array('move',);
public function setUp(): void {
parent::setUp();
global $USERINFO;
global $conf;
$conf['useacl'] = 1;
$conf['superuser'] = 'john';
$_SERVER['REMOTE_USER'] = 'john'; //now it's testing as admin
$USERINFO['grps'] = array('admin','user');
}
/**
* @coversNothing
*/
public function tearDown(): void {
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$plan->abort();
parent::tearDown();
}
/**
* @covers helper_plugin_move_plan::findAffectedPages
* @uses Doku_Indexer
*/
public function test_affectedPagesNS_Media() {
saveWikiText('oldns:start', '{{oldnsimage_missing.png}}', 'setup');
idx_addPage('oldns:start');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper','move_plan');
$this->assertFalse($plan->inProgress());
$plan->addMediaNamespaceMove('oldns', 'newns');
$plan->commit();
$affected_file = file(TMP_DIR . '/data/meta/__move_affected');
$this->assertSame('oldns:start',trim($affected_file[0]));
}
}
@@ -0,0 +1,47 @@
<?php
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
/**
* Test cases for the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_cache_handling_test extends DokuWikiTest {
function setUp(): void {
parent::setUpBeforeClass();
$this->pluginsEnabled[] = 'move';
parent::setUp();
}
/**
* @group slow
*/
function test_cache_handling() {
$testid = 'wiki:bar:test';
saveWikiText($testid,
'[[wiki:foo:]]', 'Test setup');
idx_addPage($testid);
saveWikiText('wiki:foo:start',
'bar', 'Test setup');
idx_addPage('wiki:foo:start');
sleep(1); // wait in order to make sure that conditions with < give the right result.
p_wiki_xhtml($testid); // populate cache
$cache = new cache_renderer($testid, wikiFN($testid), 'xhtml');
$this->assertTrue($cache->useCache());
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage('wiki:foo:start', 'wiki:foo2:start'));
$cache = new cache_renderer($testid, wikiFN($testid), 'xhtml');
$this->assertFalse($cache->useCache());
}
}
@@ -0,0 +1,113 @@
<?php
class helper_plugin_move_plan_findMissingDocuments_mock extends helper_plugin_move_plan {
public function findMissingDocuments($src, $dst, $type = self::TYPE_PAGES) {
parent::findMissingDocuments($src, $dst, $type);
}
public function getTmpstore() {
return $this->tmpstore;
}
}
/**
* Test cases for helper_plugin_move_plan::stepThroughDocuments function of the move plugin
*
* @group plugin_move
* @group plugin_move_unittests
* @group plugins
* @group unittests
* @covers helper_plugin_move_plan::findMissingDocuments
*/
class plugin_move_findMissingPages_test extends DokuWikiTest {
protected $pluginsEnabled = array('move',);
/** @var helper_plugin_move_plan_findMissingDocuments_mock $plan */
protected $plan;
/**
* @coversNothing
*/
public function setUp(): void {
parent::setUp();
$this->plan = new helper_plugin_move_plan_findMissingDocuments_mock();
}
/**
* @coversNothing
*/
public function tearDown(): void {
global $conf;
$dirs = array('indexdir','datadir','metadir', 'mediadir');
foreach ($dirs as $dir) {
io_rmdir($conf[$dir],true);
mkdir($conf[$dir]);
}
$this->plan->abort();
parent::tearDown();
}
function test_findMissingPages_empty () {
$this->plan->findMissingDocuments('oldns','newns:');
$tmpstore = $this->plan->getTmpstore();
$this->assertSame(array(),$tmpstore['miss']);
}
function test_findMissingPages_missingPage_default () {
saveWikiText('start','[[oldns:missing]]','test edit');
idx_addPage('start');
$this->plan->findMissingDocuments('oldns:','newns:');
$tmpstore = $this->plan->getTmpstore();
$this->assertSame(array('oldns:missing' => 'newns:missing',),$tmpstore['miss']);
}
function test_findMissingPages_missingPage_explicit () {
saveWikiText('start','[[oldns:missing]]','test edit');
idx_addPage('start');
$this->plan->findMissingDocuments('oldns:','newns:',helper_plugin_move_plan::TYPE_PAGES);
$tmpstore = $this->plan->getTmpstore();
$this->assertSame(array('oldns:missing' => 'newns:missing',),$tmpstore['miss']);
}
function test_findMissingPages_missingPage_integrated () {
saveWikiText('oldns:start','[[oldns:missing]] {{oldns:missing.png}}','test edit');
idx_addPage('oldns:start');
$this->plan->addPageNamespaceMove('oldns', 'newns');
$this->plan->addMediaNamespaceMove('oldns', 'newns');
$this->plan->commit();
$missing_file = file(TMP_DIR . '/data/meta/__move_missing');
$this->assertSame(array("oldns:missing\tnewns:missing\n",),$missing_file,'new configuration fails');
$missing_media_file = file(TMP_DIR . '/data/meta/__move_missing_media');
$this->assertSame(array("oldns:missing.png\tnewns:missing.png\n",),$missing_media_file,'new configuration fails');
}
function test_findMissingPages_missingMedia () {
saveWikiText('start','{{oldns:missing.png}}','test edit');
idx_addPage('start');
$this->plan->findMissingDocuments('oldns:','newns:',helper_plugin_move_plan::TYPE_MEDIA);
$tmpstore = $this->plan->getTmpstore();
$this->assertSame(array('oldns:missing.png' => 'newns:missing.png',),$tmpstore['miss_media']);
}
function test_findMissingDocuments_nonMissingMedia () {
$filepath = DOKU_TMP_DATA.'media/oldns/oldnsimage.png';
io_makeFileDir($filepath);
io_saveFile($filepath,'');
saveWikiText('start','{{oldns:oldnsimage.png}}','test edit');
idx_addPage('start');
$this->plan->findMissingDocuments('oldns:','newns:',helper_plugin_move_plan::TYPE_MEDIA);
$tmpstore = $this->plan->getTmpstore();
$this->assertSame(array(),$tmpstore['miss_media']);
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
require_once(__DIR__ . '/../helper/handler.php');
/**
* Test cases for the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_handler_test extends DokuWikiTest {
public function setUp(): void {
$this->pluginsEnabled[] = 'move';
parent::setUp();
}
public function test_relativeLink() {
/** @var $handler helper_plugin_move_handler */
$handler = plugin_load('helper', 'move_handler');
$handler->init('deep:namespace:page', 'used:to:be:here', array(), array(), array());
$tests = array(
'deep:namespace:new1' => 'new1',
'deep:new2' => '..:new2',
'new3' => ':new3', // absolute is shorter than relative
'deep:namespace:deeper:new4' => '.deeper:new4',
'deep:namespace:deeper:deepest:new5' => '.deeper:deepest:new5',
'deep:foobar:new6' => '..:foobar:new6',
);
foreach($tests as $new => $rel) {
$this->assertEquals($rel, $handler->relativeLink('foo', $new, 'page'));
}
$this->assertEquals('.deeper:', $handler->relativeLink('.deeper:', 'deep:namespace:deeper:start', 'page'));
$this->assertEquals('.:', $handler->relativeLink('.:', 'deep:namespace:start', 'page'));
}
public function test_resolveMoves() {
/** @var $handler helper_plugin_move_handler */
$handler = plugin_load('helper', 'move_handler');
$handler->init(
'deep:namespace:page',
'used:to:be:here',
array(
array('used:to:be:here', 'deep:namespace:page'),
array('foo', 'bar'),
array('used:to:be:this1', 'used:to:be:that1'),
array('used:to:be:this2', 'deep:namespace:that1'),
array('used:to:be:this3', 'deep:that3'),
array('deep:that3', 'but:got:moved3'),
),
array(),
array()
);
$tests = array(
'used:to:be:here' => 'deep:namespace:page', // full link to self
':foo' => 'bar', // absolute link that moved
':bang' => 'bang', // absolute link that did not move
'foo' => 'used:to:be:foo', // relative link that did not move
'this1' => 'used:to:be:that1', // relative link that did not move but is in move list
'this2' => 'deep:namespace:that1', // relative link that moved
'this3' => 'but:got:moved3', // relative link that moved twice
);
foreach($tests as $match => $id) {
$this->assertEquals($id, $handler->resolveMoves($match, 'page'));
}
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
/**
* Test cases log functionality of the move plugin
*
* @group plugin_move
* @group plugin_move_unittests
* @group plugins
* @group unittests
*/
class plugin_move_log_test extends DokuWikiTest {
protected $pluginsEnabled = array('move',);
public function test_log_one_line_success() {
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$now = time();
$date = date('Y-m-d H:i:s', $now);
$actual_log = $plan->build_log_line('P','oldpage','newpage',true);
$expected_log = "$now\t$date\tP\toldpage\tnewpage\tsuccess\t\n";
$this->assertSame($expected_log, $actual_log);
}
public function test_log_build_line_failure() {
global $MSG;
$MSG = array();
$msg = array('msg'=>"TestMessage01",);
array_push($MSG,$msg);
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$now = time();
$date = date('Y-m-d H:i:s', $now);
$actual_log = $plan->build_log_line('P','oldpage','newpage',false);
$expected_log = "$now\t$date\tP\toldpage\tnewpage\tfailed\tTestMessage01\n";
$this->assertSame($expected_log, $actual_log);
}
}
+124
View File
@@ -0,0 +1,124 @@
<?php
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
/**
* Test cases for the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_mediamove_test extends DokuWikiTest {
public function setUp(): void {
$this->pluginsEnabled[] = 'move';
parent::setUp();
}
/**
* @group slow
*/
public function test_movePageWithRelativeMedia() {
$src = 'mediareltest:foo';
saveWikiText($src,
'{{ myimage.png}} [[:start|{{ testimage.png?200x800 }}]] [[bar|{{testimage.gif?400x200}}]]
[[doku>wiki:dokuwiki|{{wiki:logo.png}}]] [[http://www.example.com|{{testimage.jpg}}]]
[[doku>wiki:foo|{{foo.gif?200x3000}}]]', 'Test setup');
idx_addPage($src);
$dst = 'foo';
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage($src, $dst));
$this->assertEquals('{{ mediareltest:myimage.png}} [[:start|{{ mediareltest:testimage.png?200x800 }}]] [[mediareltest:bar|{{mediareltest:testimage.gif?400x200}}]]
[[doku>wiki:dokuwiki|{{wiki:logo.png}}]] [[http://www.example.com|{{mediareltest:testimage.jpg}}]]
[[doku>wiki:foo|{{mediareltest:foo.gif?200x3000}}]]', rawWiki('foo'));
}
/**
* @group slow
*/
public function test_moveSingleMedia() {
global $AUTH_ACL;
$AUTH_ACL[] = "wiki:*\t@ALL\t16";
$AUTH_ACL[] = "foobar:*\t@ALL\t8";
saveWikiText('wiki:movetest', '{{wiki:dokuwiki-128.png?200}}', 'Test initialized');
idx_addPage('wiki:movetest');
$src = 'wiki:dokuwiki-128.png';
$dst = 'foobar:logo.png';
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->moveMedia($src, $dst));
$this->assertTrue(@file_exists(mediaFn('foobar:logo.png')));
$this->assertEquals('{{foobar:logo.png?200}}', rawWiki('wiki:movetest'));
}
/**
* @group slow
*/
public function test_moveSingleMedia_colonstart() {
global $AUTH_ACL;
$AUTH_ACL[] = "wiki:*\t@ALL\t16";
$AUTH_ACL[] = "foobar:*\t@ALL\t16";
$AUTH_ACL[] = "*\t@ALL\t8";
$filepath = DOKU_TMP_DATA.'media/wiki/testimage.png';
io_makeFileDir($filepath);
io_saveFile($filepath,'');
saveWikiText('wiki:movetest', '{{:wiki:testimage.png?200}}', 'Test initialized');
idx_addPage('wiki:movetest');
$src = 'wiki:testimage.png';
$dst = 'foobar:logo_2.png';
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->moveMedia($src, $dst));
$this->assertTrue(@file_exists(mediaFn('foobar:logo_2.png')));
$this->assertEquals('{{foobar:logo_2.png?200}}', rawWiki('wiki:movetest'));
$this->assertTrue($move->moveMedia($dst, 'logo_2.png'));
$this->assertTrue(@file_exists(mediaFn('logo_2.png')));
$this->assertEquals('{{:logo_2.png?200}}', rawWiki('wiki:movetest'));
}
/**
* @group slow
*/
public function test_moveSingleMedia_space() {
global $AUTH_ACL;
$AUTH_ACL[] = "wiki:*\t@ALL\t16";
$AUTH_ACL[] = "foobar:*\t@ALL\t8";
$filepath = DOKU_TMP_DATA.'media/wiki/foo/test_image.png';
io_makeFileDir($filepath);
io_saveFile($filepath,'');
saveWikiText('wiki:movetest', '{{:wiki:foo:test image.png?200|test image}}', 'Test initialized');
idx_addPage('wiki:movetest');
$src = 'wiki:foo:test_image.png';
$dst = 'wiki:foobar:test_image.png';
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->moveMedia($src, $dst));
$this->assertTrue(@file_exists(mediaFn('wiki:foobar:test_image.png')));
$this->assertEquals('{{wiki:foobar:test_image.png?200|test image}}', rawWiki('wiki:movetest'));
}
}
@@ -0,0 +1,478 @@
<?php
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
/**
* Test cases for namespace move functionality of the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_namespace_move_test extends DokuWikiTest {
public function setUp(): void {
$this->pluginsEnabled[] = 'move';
parent::setUp();
}
/**
* @coversNothing
*/
public function tearDown(): void {
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$plan->abort();
io_rmdir(DOKU_TMP_DATA."pages/newns",true);
io_rmdir(DOKU_TMP_DATA."media/newns",true);
io_rmdir(DOKU_TMP_DATA."meta/newns",true);
parent::tearDown();
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_wiki_namespace() {
global $AUTH_ACL;
$AUTH_ACL[] = "wiki:*\t@ALL\t16";
idx_addPage('wiki:dokuwiki');
idx_addPage('wiki:syntax');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('wiki', 'foo');
$plan->addMediaNamespaceMove('wiki', 'foo');
$plan->commit();
$this->assertSame(1, $plan->nextStep(),'pages');
$this->assertSame(1, $plan->nextStep(),'media');
$this->assertSame(1, $plan->nextStep(),'missing');
$this->assertSame(1, $plan->nextStep(),'namespace');
$this->assertSame(1, $plan->nextStep(),'autorewrite');
$this->assertSame(0, $plan->nextStep(),'done');
$this->assertFileExists(wikiFN('foo:dokuwiki'));
$this->assertFileNotExists(wikiFN('wiki:syntax'));
$this->assertFileExists(mediaFN('foo:dokuwiki-128.png'));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_missing() {
saveWikiText('oldspace:page', '[[missing]]', 'setup');
idx_addPage('oldspace:page');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('oldspace', 'newspace');
$plan->commit();
$this->assertSame(1, $plan->nextStep(),'page');
$this->assertSame(1, $plan->nextStep(),'missing');
$this->assertSame(1, $plan->nextStep(),'namespace');
$this->assertSame(1, $plan->nextStep(),'autorewrite');
$this->assertSame(0, $plan->nextStep(),'done');
$this->assertFileExists(wikiFN('newspace:page'));
$this->assertFileNotExists(wikiFN('oldspace:page'));
$this->assertEquals('[[missing]]', rawWiki('newspace:page'));
}
/**
* @covers helper_plugin_move_plan::findAffectedPages
* @uses Doku_Indexer
*/
public function test_move_affected() {
saveWikiText('oldaffectedspace:page', '[[missing]]', 'setup');
idx_addPage('oldaffectedspace:page');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('oldaffectedspace', 'newaffectedspace');
$plan->commit();
$affected_file = file(TMP_DIR . '/data/meta/__move_affected');
$this->assertSame('newaffectedspace:page',trim($affected_file[0]));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
function test_move_large_ns(){
$this->markTestSkipped(
'This test randomly fails with the page "testns:start" being moved, but "start" not being rewritten in the request.'
);
global $conf;
$test = '[[testns:start]] [[testns:test_page17]]';
$summary = 'testsetup';
saveWikiText(':start', $test, $summary);
idx_addPage(':start');
saveWikiText('testns:start', $test, $summary);
idx_addPage('testns:start');
saveWikiText('testns:test_page1', $test, $summary);
idx_addPage('testns:test_page1');
saveWikiText('testns:test_page2', $test, $summary);
idx_addPage('testns:test_page2');
saveWikiText('testns:test_page3', $test, $summary);
idx_addPage('testns:test_page3');
saveWikiText('testns:test_page4', $test, $summary);
idx_addPage('testns:test_page4');
saveWikiText('testns:test_page5', $test, $summary);
idx_addPage('testns:test_page5');
saveWikiText('testns:test_page6', $test, $summary);
idx_addPage('testns:test_page6');
saveWikiText('testns:test_page7', $test, $summary);
idx_addPage('testns:test_page7');
saveWikiText('testns:test_page8', $test, $summary);
idx_addPage('testns:test_page8');
saveWikiText('testns:test_page9', $test, $summary);
idx_addPage('testns:test_page9');
saveWikiText('testns:test_page10', $test, $summary);
idx_addPage('testns:test_page10');
saveWikiText('testns:test_page11', $test, $summary);
idx_addPage('testns:test_page11');
saveWikiText('testns:test_page12', $test, $summary);
idx_addPage('testns:test_page12');
saveWikiText('testns:test_page13', $test, $summary);
idx_addPage('testns:test_page13');
saveWikiText('testns:test_page14', $test, $summary);
idx_addPage('testns:test_page14');
saveWikiText('testns:test_page15', $test, $summary);
idx_addPage('testns:test_page15');
saveWikiText('testns:test_page16', $test, $summary);
idx_addPage('testns:test_page16');
saveWikiText('testns:test_page17', $test, $summary);
idx_addPage('testns:test_page17');
saveWikiText('testns:test_page18', $test, $summary);
idx_addPage('testns:test_page18');
saveWikiText('testns:test_page19', $test, $summary);
idx_addPage('testns:test_page19');
$conf['plugin']['move']['autorewrite'] = 0;
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('testns', 'foo:testns');
$plan->commit();
global $conf;
$lockfile = $conf['lockdir'] . 'move.lock';
$this->assertSame(10, $plan->nextStep(),"After processing first chunk of pages, 10 steps should be left");
$request = new TestRequest();
$response = $request->get();
$actual_response = $response->getContent();
//clean away clutter
$actual_response = substr($actual_response,strpos($actual_response,"<!-- wikipage start -->") + 23);
$actual_response = substr($actual_response,strpos($actual_response, 'doku.php'));
$actual_response = substr($actual_response,0,strpos($actual_response,"<!-- wikipage stop -->"));
$actual_response = trim($actual_response);
$actual_response = rtrim($actual_response,"</p>");
$actual_response = trim($actual_response);
$expected_response = 'doku.php?id=foo:testns:start" class="wikilink1" title="foo:testns:start">testns</a> <a href="/./doku.php?id=testns:test_page17" class="wikilink1" title="testns:test_page17">test_page17</a>';
$this->assertSame($expected_response,$actual_response); // todo: this assert fails occaisionally, but not reproduciably. It then has the following oputput: <a href="/./doku.php?id=testns:start" class="wikilink2" title="testns:start" rel="nofollow">testns</a> <a href="/./doku.php?id=testns:test_page17" class="wikilink1" title="testns:test_page17">test_page17</a>
$expected_file_contents = '[[testns:start]] [[testns:test_page17]]';
$start_file = file(TMP_DIR . '/data/pages/start.txt');
$actual_file_contents = $start_file[0];
$this->assertSame($expected_file_contents,$actual_file_contents);
/** @var helper_plugin_move_rewrite $rewrite */
$rewrite = plugin_load('helper', 'move_rewrite');
$expected_move_meta = array('origin'=> 'testns:start', 'pages' => array(array('testns:start','foo:testns:start')),'media' => array());
$actual_move_media = $rewrite->getMoveMeta('foo:testns:start');
$this->assertSame($expected_move_meta,$actual_move_media);
$this->assertFileExists($lockfile);
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_small_namespace_pages() {
global $AUTH_ACL;
$AUTH_ACL[] = "oldns:*\t@ALL\t16";
$AUTH_ACL[] = "newns:*\t@ALL\t16";
saveWikiText('start', '[[oldns:start]] [[oldns:page]] [[oldns:missing]]', 'setup');
idx_addPage('start');
saveWikiText('oldns:start', '[[oldns:start]] [[oldns:page]] [[oldns:missing]] [[missing]] [[page]]', 'setup');
idx_addPage('oldns:start');
saveWikiText('oldns:page', '[[oldns:start]] [[oldns:page]] [[oldns:missing]] [[missing]] [[start]]', 'setup');
idx_addPage('oldns:page');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('oldns', 'newns');
$plan->commit();
$this->assertSame(1, $plan->nextStep(), 'pages');
$this->assertSame(1, $plan->nextStep(), 'missing');
$this->assertSame(1, $plan->nextStep(), 'namespace');
$this->assertSame(1, $plan->nextStep(), 'autorewrite');
$this->assertSame(0, $plan->nextStep(), 'done');
$this->assertFileExists(wikiFN('newns:start'));
$this->assertFileExists(wikiFN('newns:page'));
$this->assertFileNotExists(wikiFN('oldns:start'));
$this->assertFileNotExists(wikiFN('oldns:page'));
$this->assertSame('[[newns:start]] [[newns:page]] [[newns:missing]] [[missing]] [[page]]',rawWiki('newns:start'));
$this->assertSame('[[newns:start]] [[newns:page]] [[newns:missing]] [[missing]] [[start]]',rawWiki('newns:page'));
$this->assertSame('[[newns:start]] [[newns:page]] [[newns:missing]]',rawWiki('start'));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_small_namespace_media() {
global $AUTH_ACL;
$AUTH_ACL[] = "oldns:*\t@ALL\t16";
$AUTH_ACL[] = "newns:*\t@ALL\t16";
$filepath = DOKU_TMP_DATA.'media/oldns/oldnsimage.png';
io_makeFileDir($filepath);
io_saveFile($filepath,'');
saveWikiText('start', '{{oldns:oldnsimage.png}} {{oldns:oldnsimage_missing.png}} {{image_missing.png}}', 'setup');
idx_addPage('start');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addMediaNamespaceMove('oldns', 'newns');
$plan->commit();
$this->assertSame(1, $plan->nextStep(), 'media');
$this->assertSame(1, $plan->nextStep(), 'missing_media');
$this->assertSame(1, $plan->nextStep(), 'autorewrite');
$this->assertSame(0, $plan->nextStep(), 'done');
$this->assertFileExists(mediaFN('newns:oldnsimage.png'));
$this->assertFileNotExists(mediaFN('oldns:oldnsimage.png'));
$this->assertSame('{{newns:oldnsimage.png}} {{newns:oldnsimage_missing.png}} {{image_missing.png}}',rawWiki('start'));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_small_namespace_media_affected() {
global $AUTH_ACL;
$AUTH_ACL[] = "oldns:*\t@ALL\t16";
$AUTH_ACL[] = "newns:*\t@ALL\t16";
$filepath = DOKU_TMP_DATA.'media/oldns/oldnsimage.png';
io_makeFileDir($filepath);
io_saveFile($filepath,'');
saveWikiText('oldns:start', '{{:oldns:oldnsimage.png}} {{oldns:oldnsimage_missing.png}} {{oldnsimage_missing.png}} {{oldnsimage.png}}', 'setup');
idx_addPage('oldns:start');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addMediaNamespaceMove('oldns', 'newns');
$plan->commit();
$this->assertSame(1, $plan->nextStep(), 'media');
$this->assertSame(1, $plan->nextStep(), 'missing_media');
$this->assertSame(1, $plan->nextStep(), 'autorewrite');
$this->assertSame(0, $plan->nextStep(), 'done');
$this->assertFileExists(mediaFN('newns:oldnsimage.png'));
$this->assertFileNotExists(mediaFN('oldns:oldnsimage.png'));
$this->assertSame('{{newns:oldnsimage.png}} {{newns:oldnsimage_missing.png}} {{newns:oldnsimage_missing.png}} {{newns:oldnsimage.png}}',rawWiki('oldns:start'));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_small_namespace_combi() {
global $AUTH_ACL;
$AUTH_ACL[] = "oldns:*\t@ALL\t16";
$AUTH_ACL[] = "newns:*\t@ALL\t16";
$filepath = DOKU_TMP_DATA.'media/oldns/oldnsimage.png';
io_makeFileDir($filepath);
io_saveFile($filepath,'');
saveWikiText('start', "[[oldns:start]] [[oldns:page]] [[oldns:missing]]\n{{oldns:oldnsimage.png}} {{oldns:oldnsimage_missing.png}} {{oldnsimage_missing.png}}", 'setup');
idx_addPage('start');
saveWikiText('oldns:start', '[[oldns:start]] [[oldns:page]] [[oldns:missing]] [[missing]] [[page]]', 'setup');
idx_addPage('oldns:start');
saveWikiText('oldns:page', '[[oldns:start]] [[oldns:page]] [[oldns:missing]] [[missing]] [[start]]', 'setup');
idx_addPage('oldns:page');
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addMediaNamespaceMove('oldns', 'newns');
$plan->addPageNamespaceMove('oldns', 'newns');
$plan->commit();
$this->assertSame(1, $plan->nextStep(), 'pages');
$this->assertSame(1, $plan->nextStep(), 'media');
$this->assertSame(1, $plan->nextStep(), 'missing');
$this->assertSame(1, $plan->nextStep(), 'missing_media');
$this->assertSame(1, $plan->nextStep(), 'namespaces');
$this->assertSame(1, $plan->nextStep(), 'autorewrite');
$this->assertSame(0, $plan->nextStep(), 'done');
$this->assertFileExists(mediaFN('newns:oldnsimage.png'));
$this->assertFileNotExists(mediaFN('oldns:oldnsimage.png'));
$this->assertSame("[[newns:start]] [[newns:page]] [[newns:missing]]\n{{newns:oldnsimage.png}} {{newns:oldnsimage_missing.png}} {{oldnsimage_missing.png}}",rawWiki('start'));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_small_namespace_subscription_ns() {
global $AUTH_ACL;
$AUTH_ACL[] = "subns:*\t@ALL\t16";
$AUTH_ACL[] = "newns:*\t@ALL\t16";
saveWikiText('subns:start', 'Lorem Ipsum', 'setup');
idx_addPage('subns:start');
$oldfilepath = DOKU_TMP_DATA.'meta/subns/.mlist';
$subscription = 'doe every 1427984341';
io_makeFileDir($oldfilepath);
io_saveFile($oldfilepath,$subscription);
$newfilepath = DOKU_TMP_DATA.'meta/newns/.mlist';
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('subns', 'newns');
$plan->commit();
$this->assertSame(1, $plan->nextStep(), 'pages');
$this->assertSame(1, $plan->nextStep(), 'namespace');
$this->assertSame(0, $plan->nextStep(), 'done');
$this->assertFileExists(wikiFN('newns:start'));
$this->assertFileExists($newfilepath);
$this->assertFileNotExists(wikiFN('subns:start'));
$this->assertFileNotExists($oldfilepath);
$this->assertSame($subscription,file_get_contents($newfilepath));
}
/**
* This is an integration test, which checks the correct working of an entire namespace move.
* Hence it is not an unittest, hence it @coversNothing
*
* @group slow
*/
public function test_move_small_namespace_subscription_page() {
global $AUTH_ACL;
$AUTH_ACL[] = "subns:*\t@ALL\t16";
$AUTH_ACL[] = "newns:*\t@ALL\t16";
saveWikiText('subns:start', 'Lorem Ipsum', 'setup');
idx_addPage('subns:start');
$oldfilepath = DOKU_TMP_DATA.'meta/subns/start.mlist';
$subscription = 'doe every 1427984341';
io_makeFileDir($oldfilepath);
io_saveFile($oldfilepath,$subscription);
$newfilepath = DOKU_TMP_DATA.'meta/newns/start.mlist';
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
$this->assertFalse($plan->inProgress());
$plan->addPageNamespaceMove('subns', 'newns');
$plan->commit();
$this->assertSame(1, $plan->nextStep(), 'pages');
$this->assertSame(1, $plan->nextStep(), 'namespace');
$this->assertSame(0, $plan->nextStep(), 'done');
$this->assertFileExists(wikiFN('newns:start'));
$this->assertFileExists($newfilepath);
$this->assertFileNotExists(wikiFN('subns:start'));
$this->assertFileNotExists($oldfilepath);
$this->assertSame($subscription,file_get_contents($newfilepath));
}
}
+629
View File
@@ -0,0 +1,629 @@
<?php
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
/**
* Test cases for the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_pagemove_test extends DokuWikiTest {
var $movedToId = '';
var $movedId = 'parent_ns:current_ns:test_page';
var $parentBacklinkingId = 'parent_ns:some_page';
var $currentNsBacklinkingId = 'parent_ns:current_ns:some_page';
var $otherBacklinkingId = 'level0:level1:other_backlinking_page';
var $subNsPage = 'parent_ns:current_ns:sub_ns:some_page';
// @todo Move page to an ID which already exists
// @todo Check backlinks of a sub-namespace page (moving same, up, down, different)
function setUp(): void {
parent::setUpBeforeClass();
$this->pluginsEnabled[] = 'move';
global $ID;
global $INFO;
global $conf;
$ID = $this->movedId;
$text = <<<EOT
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$summary = 'Test';
saveWikiText($this->movedId, $text, $summary);
$INFO = pageinfo();
$references = array_keys(p_get_metadata($this->movedId, 'relation references', METADATA_RENDER_UNLIMITED));
idx_get_indexer()->addMetaKeys($this->movedId, 'relation_references', $references);
$text = <<<EOT
[[$this->movedId|$this->movedId]]
[[:$this->movedId|:$this->movedId]]
[[.current_ns:test_page|.current_ns:test_page]]
[[.:current_ns:test_page|.:current_ns:test_page]]
[[..parent_ns:current_ns:test_page|..parent_ns:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
saveWikiText($this->parentBacklinkingId, $text, $summary);
$references = array_keys(p_get_metadata($this->parentBacklinkingId, 'relation references', METADATA_RENDER_UNLIMITED));
idx_get_indexer()->addMetaKeys($this->parentBacklinkingId, 'relation_references', $references);
$text = <<<EOT
[[$this->movedId|$this->movedId]]
[[:$this->movedId|:$this->movedId]]
[[..current_ns:test_page|..current_ns:test_page]]
[[..:current_ns:test_page|..:current_ns:test_page]]
[[test_page|test_page]]
[[.test_page|.test_page]]
[[.:test_page|.:test_page]]
[[..test_page|..test_page]]
[[..:test_page|..:test_page]]
[[.:..:test_page|.:..:test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
saveWikiText($this->currentNsBacklinkingId, $text, $summary);
$references = array_keys(p_get_metadata($this->currentNsBacklinkingId, 'relation references', METADATA_RENDER_UNLIMITED));
idx_get_indexer()->addMetaKeys($this->currentNsBacklinkingId, 'relation_references', $references);
$text = <<<EOT
[[$this->movedId|$this->movedId]]
[[:$this->movedId|:$this->movedId]]
[[.current_ns:test_page|.current_ns:test_page]]
[[.:current_ns:test_page|.:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
saveWikiText($this->otherBacklinkingId, $text, $summary);
$references = array_keys(p_get_metadata($this->otherBacklinkingId, 'relation references', METADATA_RENDER_UNLIMITED));
idx_get_indexer()->addMetaKeys($this->otherBacklinkingId, 'relation_references', $references);
$text = <<<EOT
[[$this->movedId|$this->movedId]]
[[:$this->movedId|:$this->movedId]]
[[..:..current_ns:test_page|..:..current_ns:test_page]]
[[..:..:current_ns:test_page|..:..:current_ns:test_page]]
[[test_page|test_page]]
[[..:test_page|..:test_page]]
[[..:test_page|..:test_page]]
[[.:..:test_page|.:..:test_page]]
[[new_page|new_page]]
[[..:new_page|..:new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
saveWikiText($this->subNsPage, $text, $summary);
$references = array_keys(p_get_metadata($this->subNsPage, 'relation references', METADATA_RENDER_UNLIMITED));
idx_get_indexer()->addMetaKeys($this->subNsPage, 'relation_references', $references);
parent::setUp();
// we test under useslash conditions
$conf['useslash'] = 1;
}
/**
* @group slow
*/
function test_move_page_in_same_ns() {
global $ID;
$newId = getNS($ID).':new_page';
$this->movedToId = $newId;
/** @var helper_plugin_move_op $MoveOp */
$MoveOp = plugin_load('helper', 'move_op');
$result = $MoveOp->movePage($ID, $this->movedToId);
$this->assertTrue($result);
$newContent = rawWiki($this->movedToId);
$expectedContent = <<<EOT
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->parentBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:current_ns:new_page|$this->movedId]]
[[parent_ns:current_ns:new_page|:$this->movedId]]
[[.current_ns:new_page|.current_ns:test_page]]
[[.current_ns:new_page|.:current_ns:test_page]]
[[.current_ns:new_page|..parent_ns:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->currentNsBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:current_ns:new_page|$this->movedId]]
[[parent_ns:current_ns:new_page|:$this->movedId]]
[[new_page|..current_ns:test_page]]
[[new_page|..:current_ns:test_page]]
[[new_page|test_page]]
[[new_page|.test_page]]
[[new_page|.:test_page]]
[[..test_page|..test_page]]
[[..:test_page|..:test_page]]
[[.:..:test_page|.:..:test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->otherBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:current_ns:new_page|$this->movedId]]
[[$newId|:$this->movedId]]
[[.current_ns:test_page|.current_ns:test_page]]
[[.:current_ns:test_page|.:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
}
/**
* @group slow
*/
function test_move_page_to_parallel_ns() {
global $ID;
$newId = 'parent_ns:parallel_ns:new_page';
$this->movedToId = $newId;
/** @var helper_plugin_move_op $MoveOp */
$MoveOp = plugin_load('helper', 'move_op');
$result = $MoveOp->movePage($ID, $newId);
$this->assertTrue($result);
$newContent = rawWiki($this->movedToId);
$expectedContent = <<<EOT
[[..:current_ns:start|start]]
[[..:current_ns:parallel_page|parallel_page]]
[[..:current_ns:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->parentBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:parallel_ns:new_page|$this->movedId]]
[[parent_ns:parallel_ns:new_page|:$this->movedId]]
[[.parallel_ns:new_page|.current_ns:test_page]]
[[.parallel_ns:new_page|.:current_ns:test_page]]
[[.parallel_ns:new_page|..parent_ns:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->currentNsBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:parallel_ns:new_page|$this->movedId]]
[[$newId|:$this->movedId]]
[[..:parallel_ns:new_page|..current_ns:test_page]]
[[..:parallel_ns:new_page|..:current_ns:test_page]]
[[..:parallel_ns:new_page|test_page]]
[[..:parallel_ns:new_page|.test_page]]
[[..:parallel_ns:new_page|.:test_page]]
[[..test_page|..test_page]]
[[..:test_page|..:test_page]]
[[.:..:test_page|.:..:test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->otherBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:parallel_ns:new_page|$this->movedId]]
[[$newId|:$this->movedId]]
[[.current_ns:test_page|.current_ns:test_page]]
[[.:current_ns:test_page|.:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
}
/**
* @group slow
*/
function test_move_page_to_parent_ns() {
global $ID;
$newId = 'parent_ns:new_page';
$this->movedToId = $newId;
/** @var helper_plugin_move_op $MoveOp */
$MoveOp = plugin_load('helper', 'move_op');
$result = $MoveOp->movePage($ID, $newId); //parent_ns:current_ns:test_page -> parent_ns:new_page
$this->assertTrue($result);
$newContent = rawWiki($this->movedToId);
$expectedContent = <<<EOT
[[.current_ns:start|start]]
[[.current_ns:parallel_page|parallel_page]]
[[.current_ns:|.:]]
[[.current_ns:|..current_ns:]]
[[.current_ns:|..:current_ns:]]
[[.parallel_ns:|..parallel_ns:]]
[[.parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
// Note: ..:..: is not a great link for a page in a namespace 'parent_ns', but it is correctly resolved.
$this->assertEquals($expectedContent, $newContent);
// page is moved to same NS as backlinking page (parent_ns)
$newContent = rawWiki($this->parentBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:new_page|$this->movedId]]
[[parent_ns:new_page|:$this->movedId]]
[[new_page|.current_ns:test_page]]
[[new_page|.:current_ns:test_page]]
[[new_page|..parent_ns:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->currentNsBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:new_page|$this->movedId]]
[[$newId|:$this->movedId]]
[[..:new_page|..current_ns:test_page]]
[[..:new_page|..:current_ns:test_page]]
[[..:new_page|test_page]]
[[..:new_page|.test_page]]
[[..:new_page|.:test_page]]
[[..test_page|..test_page]]
[[..:test_page|..:test_page]]
[[.:..:test_page|.:..:test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
$newContent = rawWiki($this->otherBacklinkingId);
$expectedContent = <<<EOT
[[parent_ns:new_page|$this->movedId]]
[[$newId|:$this->movedId]]
[[.current_ns:test_page|.current_ns:test_page]]
[[.:current_ns:test_page|.:current_ns:test_page]]
[[test_page|test_page]]
[[new_page|new_page]]
[[ftp://somewhere.com|ftp://somewhere.com]]
[[http://somewhere.com|http://somewhere.com]]
[[start|start]]
[[parallel_page|parallel_page]]
[[.:|.:]]
[[..current_ns:|..current_ns:]]
[[..:current_ns:|..:current_ns:]]
[[..parallel_ns:|..parallel_ns:]]
[[..:parallel_ns:|..:parallel_ns:]]
[[..:..:|..:..:]]
[[..:..:parent_ns:|..:..:parent_ns:]]
[[parent_ns:new_page|parent_ns:new_page]]
[[parent_ns/new_page|parent_ns/new_page]]
[[/start|/start]]
EOT;
$this->assertEquals($expectedContent, $newContent);
}
/**
* Ensure that absolute links stay absolute. See https://github.com/michitux/dokuwiki-plugin-move/pull/6#discussion_r15698440
*
* @group slow
*/
function test_move_startpage_of_ns() {
saveWikiText('wiki:bar:test',
'[[wiki:foo:]]', 'Test setup');
idx_addPage('wiki:bar:test');
saveWikiText('wiki:foo:start',
'bar', 'Test setup');
idx_addPage('wiki:foo:start');
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage('wiki:foo:start', 'wiki:foo2:start'));
$this->assertEquals('[[wiki:foo2:]]', rawWiki('wiki:bar:test'));
}
/**
* If the relative part would be too large, create an absolute link instead.
* If the original link ended with a colon and the new link also points to a namespace's startpage: keep the colon.
*
* @group slow
*/
function test_move_no_long_rel_links_keep_colon() {
saveWikiText('wiki:foo:start', '[[..:..:one_ns_up:]]', 'Test setup');
idx_addPage('wiki:foo:start');
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage('wiki:foo:start', 'wiki:foo:bar:start'));
$this->assertEquals('[[one_ns_up:]]', rawWiki('wiki:foo:bar:start'));
}
/**
* @covers helper_plugin_move_handler::_nsStartCheck
* @group slow
*/
function test_move_to_thisns_start(){
saveWikiText('wiki:foo:test_page', '[[..:..:bar:]]', 'Test setup');
idx_addPage('wiki:foo:test_page');
saveWikiText('bar:start', 'foo', 'Test setup');
idx_addPage('bar:start');
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage('bar:start', 'wiki:foo:start'));
$this->assertEquals('[[.:]]', rawWiki('wiki:foo:test_page'));
}
function test_move_ns_in_same_ns() {
$newNamespace = 'new_ns';
$newPagename = '';
$opts = array();
$opts['page_ns'] = 'ns';
$opts['newns'] = 'parent_ns'.':'.$newNamespace;
$opts['newname'] = $newPagename;
$this->movedToId = $opts['newns'].':'.$newPagename;
//$this->move->_pm_move_recursive($opts);
$this->markTestIncomplete('Test must yet be implemented.');
}
function test_move_start_ns_into_ns_page() {
saveWikiText('bugs:start', 'Bug page', 'created');
idx_addPage('bugs:start');
saveWikiText('foo:bugs:test', '[[bugs:start]]', 'created');
idx_addPage('foo:bugs:test');
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage('bugs:start', 'bugs'));
$this->assertEquals('[[:bugs]]', rawWiki('foo:bugs:test'));
$this->assertTrue($move->movePage('bugs', 'start'));
$this->assertEquals('[[:start]]', rawWiki('foo:bugs:test'));
}
function test_clean_id_move() {
saveWikiText('some_space:start', 'Space page', 'created');
idx_addPage('some_space:start');
saveWikiText('foo:bar:test', '[[some space:start]]', 'created');
idx_addPage('foo:bar:test');
/** @var helper_plugin_move_op $move */
$move = plugin_load('helper', 'move_op');
$this->assertTrue($move->movePage('some_space:start', 'spaceless:start'));
$this->assertEquals('[[spaceless:start]]', rawWiki('foo:bar:test'));
}
}
+110
View File
@@ -0,0 +1,110 @@
<?php
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
require_once(__DIR__ . '/../helper/plan.php');
/**
* Test cases for the move plugin
*
* @group plugin_move
* @group plugins
*/
class plugin_move_plan_test extends DokuWikiTest {
/**
* Create some page namespace structure
*/
function setUp():void {
$pages = array(
'animals:mammals:bear:brownbear',
'animals:mammals:bear:blackbear',
'animals:mammals:cute:otter',
'animals:mammals:cute:cat',
'animals:mammals:cute:dog',
'animals:insects:butterfly:fly',
'animals:insects:butterfly:moth',
'animals:monkey',
'humans:programmers:andi',
'humans:programmers:joe',
'humans:programmers:john',
'yeti'
);
foreach($pages as $page) {
saveWikiText($page, $page, 'test setup');
}
parent::setUp();
}
/**
* Check that the plan is sorted into the right order
*/
function test_sorting() {
$plan = new test_helper_plugin_move_plan();
$plan->addPageNamespaceMove('animals:mammals:bear', 'animals:mammals:cute:bear');
$plan->addPageNamespaceMove('humans:programmers', 'animals:mammals:cute:programmers');
$plan->addPageMove('humans:programmers:andi', 'animals:insects:butterfly:andi');
$plan->addPageMove('yeti', 'humans:yeti');
$plan->addPageMove('animals:monkey', 'monkey');
$sorted = $plan->sortedPlan();
// the plan is sorted FORWARD (first things first)
$this->assertEquals(5, count($sorted));
$this->assertEquals('humans:programmers:andi', $sorted[0]['src']);
$this->assertEquals('animals:monkey', $sorted[1]['src']);
$this->assertEquals('yeti', $sorted[2]['src']);
$this->assertEquals('animals:mammals:bear', $sorted[3]['src']);
$this->assertEquals('humans:programmers', $sorted[4]['src']);
}
/**
* Move a page out of a namespace and then move the namespace elsewhere
*/
function test_pageinnamespace() {
$plan = new test_helper_plugin_move_plan();
$plan->addPageNamespaceMove('animals:mammals:cute', 'animals:mammals:funny');
$plan->addPageMove('animals:mammals:cute:otter', 'animals:mammals:otter');
$plan->commit();
$list = $plan->getList('pagelist');
// the files are sorted BACKWARDS (first things last)
$this->assertEquals(3, count($list));
$this->assertEquals("animals:mammals:cute:otter\tanimals:mammals:otter", trim($list[2]));
$this->assertEquals("animals:mammals:cute:cat\tanimals:mammals:funny:cat", trim($list[1]));
$this->assertEquals("animals:mammals:cute:dog\tanimals:mammals:funny:dog", trim($list[0]));
}
}
/**
* Class test_helper_plugin_move_plan
*
* gives access to some internal stuff of the class
*/
class test_helper_plugin_move_plan extends helper_plugin_move_plan {
/**
* Access the sorted plan
*
* @return array
*/
function sortedPlan() {
usort($this->plan, array($this, 'planSorter'));
return $this->plan;
}
/**
* Get the full saved list specified by name
*
* @param $name
* @return array
*/
function getList($name) {
return file($this->files[$name]);
}
}
@@ -0,0 +1,274 @@
<?php
/**
* mock class to access the helper_plugin_move_plan::stepThroughDocuments function in tests
*/
class helper_plugin_move_plan_mock extends helper_plugin_move_plan {
public $moveLog = array();
public function __construct() {
parent::__construct();
$this->MoveOperator = new helper_plugin_move_op_mock;
}
public function stepThroughDocumentsCall($type = parent::TYPE_PAGES, $skip = false) {
return $this->stepThroughDocuments($type, $skip);
}
public function getMoveOperator() {
return $this->MoveOperator;
}
public function setMoveOperator($newMoveOPerator) {
$this->MoveOperator = $newMoveOPerator;
}
public function build_log_line($type, $from, $to, $success) {
$logEntry = array($type,$from,$to,$success);
array_push($this->moveLog,$logEntry);
return parent::build_log_line($type, $from, $to, $success);
}
}
class helper_plugin_move_op_mock extends helper_plugin_move_op {
public $movedPages = array();
public $fail = false;
public function movePage($src, $dst) {
if ($this->fail !== false && count($this->movedPages) == $this->fail) {
$this->fail=false;
// Store a msg as it is expected by the plugin
msg("Intentional failure in test case.", -1);
return false;
}
$moveOperation = array($src => $dst);
array_push($this->movedPages,$moveOperation);
return true;
}
}
/**
* Test cases for helper_plugin_move_plan::stepThroughDocuments function of the move plugin
*
* @group plugin_move
* @group plugin_move_unittests
* @group plugins
* @group unittests
*/
class plugin_move_stepThroughDocuments_test extends DokuWikiTest {
public function setUp(): void {
parent::setUp();
$opts_file = dirname(DOKU_CONF) . '/data/meta/__move_opts';
if(file_exists($opts_file)){
unlink($opts_file);
}
$file = "oldns:page01\tnewns:page01\n"
. "oldns:page02\tnewns:page02\n"
. "oldns:page03\tnewns:page03\n"
. "oldns:page04\tnewns:page04\n"
. "oldns:page05\tnewns:page05\n"
. "oldns:page06\tnewns:page06\n"
. "oldns:page07\tnewns:page07\n"
. "oldns:page08\tnewns:page08\n"
. "oldns:page09\tnewns:page09\n"
. "oldns:page10\tnewns:page10\n"
. "oldns:page11\tnewns:page11\n"
. "oldns:page12\tnewns:page12\n"
. "oldns:page13\tnewns:page13\n"
. "oldns:page14\tnewns:page14\n"
. "oldns:page15\tnewns:page15\n"
. "oldns:page16\tnewns:page16\n"
. "oldns:page17\tnewns:page17\n"
. "oldns:page18\tnewns:page18";
$file_path = dirname(DOKU_CONF) . '/data/meta/__move_pagelist';
io_saveFile($file_path,$file);
}
/**
* @covers helper_plugin_move_plan::stepThroughDocuments
*/
public function test_stepThroughPages() {
$file_path = dirname(DOKU_CONF) . '/data/meta/__move_pagelist';
$mock = new helper_plugin_move_plan_mock();
$actual_return = $mock->stepThroughDocumentsCall();
$actual_file = file_get_contents($file_path);
$expected_file = "oldns:page01\tnewns:page01\n"
. "oldns:page02\tnewns:page02\n"
. "oldns:page03\tnewns:page03\n"
. "oldns:page04\tnewns:page04\n"
. "oldns:page05\tnewns:page05\n"
. "oldns:page06\tnewns:page06\n"
. "oldns:page07\tnewns:page07\n"
. "oldns:page08\tnewns:page08";
$expected_pages_run = -10;
$this->assertSame($expected_pages_run,$actual_return,"return values differ");
$this->assertSame($expected_file,$actual_file, "files differ");
$actual_move_Operator = $mock->getMoveOperator();
$this->assertSame(array('oldns:page18' => 'newns:page18',),$actual_move_Operator->movedPages[0]);
$this->assertSame(array('oldns:page09' => 'newns:page09',),$actual_move_Operator->movedPages[9]);
$this->assertTrue(!isset($actual_move_Operator->movedPages[10]));
$expected_log = array('P','oldns:page18','newns:page18',true);
$this->assertSame($expected_log,$mock->moveLog[0]);
$expected_log = array('P','oldns:page09','newns:page09',true);
$this->assertSame($expected_log,$mock->moveLog[9]);
$this->assertTrue(!isset($mock->moveLog[10]));
$opts_file = dirname(DOKU_CONF) . '/data/meta/__move_opts';
$actual_options = unserialize(io_readFile($opts_file));
$this->assertSame($expected_pages_run,$actual_options['pages_run'],'saved options are wrong');
}
/**
* @covers helper_plugin_move_plan::stepThroughDocuments
*/
public function test_stepThroughPages_skip() {
$file_path = dirname(DOKU_CONF) . '/data/meta/__move_pagelist';
$mock = new helper_plugin_move_plan_mock();
$actual_return = $mock->stepThroughDocumentsCall(1,true);
$actual_file = file_get_contents($file_path);
$expected_file = "oldns:page01\tnewns:page01\n"
. "oldns:page02\tnewns:page02\n"
. "oldns:page03\tnewns:page03\n"
. "oldns:page04\tnewns:page04\n"
. "oldns:page05\tnewns:page05\n"
. "oldns:page06\tnewns:page06\n"
. "oldns:page07\tnewns:page07\n"
. "oldns:page08\tnewns:page08";
$expected_pages_run = -10;
$this->assertSame($expected_pages_run,$actual_return,"return values differ");
$this->assertSame($expected_file,$actual_file, "files differ");
$actual_move_Operator = $mock->getMoveOperator();
$this->assertSame(array('oldns:page17' => 'newns:page17',),$actual_move_Operator->movedPages[0]);
$this->assertSame(array('oldns:page09' => 'newns:page09',),$actual_move_Operator->movedPages[8]);
$this->assertTrue(!isset($actual_move_Operator->movedPages[9]));
$expected_log = array('P','oldns:page17','newns:page17',true);
$this->assertSame($expected_log,$mock->moveLog[0]);
$expected_log = array('P','oldns:page09','newns:page09',true);
$this->assertSame($expected_log,$mock->moveLog[8]);
$this->assertTrue(!isset($mock->moveLog[9]));
$opts_file = dirname(DOKU_CONF) . '/data/meta/__move_opts';
$actual_options = unserialize(io_readFile($opts_file));
$this->assertSame($expected_pages_run,$actual_options['pages_run'],'saved options are wrong');
}
/**
* @covers helper_plugin_move_plan::stepThroughDocuments
*/
public function test_stepThroughPages_fail() {
$file_path = dirname(DOKU_CONF) . '/data/meta/__move_pagelist';
$mock = new helper_plugin_move_plan_mock();
$fail_at_item = 5;
$actual_move_Operator = $mock->getMoveOperator();
$actual_move_Operator->fail = $fail_at_item;
$mock->setMoveOperator($actual_move_Operator);
$actual_return = $mock->stepThroughDocumentsCall();
$actual_file = file_get_contents($file_path);
$expected_file = "oldns:page01\tnewns:page01\n"
. "oldns:page02\tnewns:page02\n"
. "oldns:page03\tnewns:page03\n"
. "oldns:page04\tnewns:page04\n"
. "oldns:page05\tnewns:page05\n"
. "oldns:page06\tnewns:page06\n"
. "oldns:page07\tnewns:page07\n"
. "oldns:page08\tnewns:page08\n"
. "oldns:page09\tnewns:page09\n"
. "oldns:page10\tnewns:page10\n"
. "oldns:page11\tnewns:page11\n"
. "oldns:page12\tnewns:page12\n"
. "oldns:page13\tnewns:page13";
$expected_pages_run = false;
$this->assertSame($expected_pages_run,$actual_return,"return values differ");
$this->assertSame($expected_file,$actual_file, "files differ");
$actual_move_Operator = $mock->getMoveOperator();
$this->assertSame(array('oldns:page18' => 'newns:page18',),$actual_move_Operator->movedPages[0]);
$lastIndex = 4;
$this->assertSame(array('oldns:page14' => 'newns:page14',),$actual_move_Operator->movedPages[$lastIndex]);
$this->assertTrue(!isset($actual_move_Operator->movedPages[$lastIndex + 1]));
$expected_log = array('P','oldns:page13','newns:page13',false);
$this->assertSame($expected_log,$mock->moveLog[5]);
$this->assertTrue(!isset($mock->moveLog[6]));
$opts_file = dirname(DOKU_CONF) . '/data/meta/__move_opts';
$actual_options = unserialize(io_readFile($opts_file));
$this->assertSame(-$fail_at_item,$actual_options['pages_run'],'saved options are wrong');
}
/**
* @covers helper_plugin_move_plan::stepThroughDocuments
*/
public function test_stepThroughPages_fail_autoskip() {
global $conf;
$conf['plugin']['move']['autoskip'] = '1';
$file_path = dirname(DOKU_CONF) . '/data/meta/__move_pagelist';
$mock = new helper_plugin_move_plan_mock();
$actual_move_Operator = $mock->getMoveOperator();
$actual_move_Operator->fail = 5;
$mock->setMoveOperator($actual_move_Operator);
$actual_return = $mock->stepThroughDocumentsCall();
$expected_pages_run = -10;
$this->assertSame($expected_pages_run,$actual_return,"return values differ");
$actual_file = file_get_contents($file_path);
$expected_file = "oldns:page01\tnewns:page01\n"
. "oldns:page02\tnewns:page02\n"
. "oldns:page03\tnewns:page03\n"
. "oldns:page04\tnewns:page04\n"
. "oldns:page05\tnewns:page05\n"
. "oldns:page06\tnewns:page06\n"
. "oldns:page07\tnewns:page07\n"
. "oldns:page08\tnewns:page08";
$this->assertSame($expected_file,$actual_file, "files differ");
$actual_move_Operator = $mock->getMoveOperator();
$this->assertSame(array('oldns:page18' => 'newns:page18',),$actual_move_Operator->movedPages[0]);
$lastIndex = 8;
$this->assertSame(array('oldns:page09' => 'newns:page09',),$actual_move_Operator->movedPages[$lastIndex]);
$this->assertTrue(!isset($actual_move_Operator->movedPages[$lastIndex + 1]), "The number of moved pages is incorrect");
$expected_log = array('P','oldns:page18','newns:page18',true);
$this->assertSame($expected_log,$mock->moveLog[0]);
$expected_log = array('P','oldns:page13','newns:page13',false);
$this->assertSame($expected_log,$mock->moveLog[5]);
$expected_log = array('P','oldns:page09','newns:page09',true);
$this->assertSame($expected_log,$mock->moveLog[9]);
$this->assertTrue(!isset($mock->moveLog[10]), "The number of logged items is incorrect");
$opts_file = dirname(DOKU_CONF) . '/data/meta/__move_opts';
$actual_options = unserialize(io_readFile($opts_file));
$this->assertSame($expected_pages_run,$actual_options['pages_run'],'saved options are wrong');
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
/**
* tests for the template button of the move plugin
*
* @author Michael Große <grosse@cosmocode.de>
* @group plugin_move
* @group plugins
*/
class move_tpl_test extends DokuWikiTest {
public function setUp(): void {
parent::setUp();
}
protected $pluginsEnabled = array('move');
/**
* @coversNothing
* Integration-ish kind of test testing action_plugin_move_rename::handle_pagetools
*//*
function test_tpl () {
saveWikiText('wiki:foo:start', '[[..:..:one_ns_up:]]', 'Test setup');
idx_addPage('wiki:foo:start');
$request = new TestRequest();
$response = $request->get(array(),'/doku.php?id=wiki:foo:start');
$this->assertTrue(strstr($response->getContent(),'class="plugin_move_page"') !== false);
}*/
/**
* @covers action_plugin_move_rename::renameOkay
*/
function test_renameOkay() {
global $conf;
global $USERINFO;
$conf['superuser'] = 'john';
$_SERVER['REMOTE_USER'] = 'john';
$USERINFO['grps'] = array('admin','user');
saveWikiText('wiki:foo:start', '[[..:..:one_ns_up:]]', 'Test setup');
idx_addPage('wiki:foo:start');
$move_rename = new action_plugin_move_rename();
$this->assertTrue($move_rename->renameOkay('wiki:foo:start'));
}
}
+66
View File
@@ -0,0 +1,66 @@
<?php
/**
* Move Plugin AJAX handler to step through a move plan
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class action_plugin_move_progress
*/
class action_plugin_move_progress extends DokuWiki_Action_Plugin {
/**
* Register event handlers.
*
* @param Doku_Event_Handler $controller The plugin controller
*/
public function register(Doku_Event_Handler $controller) {
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax');
}
/**
* Step up
*
* @param Doku_Event $event
*/
public function handle_ajax(Doku_Event $event) {
if($event->data != 'plugin_move_progress') return;
$event->preventDefault();
$event->stopPropagation();
global $INPUT;
global $USERINFO;
if(!auth_ismanager($_SERVER['REMOTE_USER'], $USERINFO['grps'])) {
http_status(403);
exit;
}
$return = array(
'error' => '',
'complete' => false,
'progress' => 0
);
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
if(!$plan->isCommited()) {
// There is no plan. Something went wrong
$return['complete'] = true;
} else {
$todo = $plan->nextStep($INPUT->bool('skip'));
$return['progress'] = $plan->getProgress();
$return['error'] = $plan->getLastError();
if($todo === 0) $return['complete'] = true;
}
$json = new JSON();
header('Content-Type: application/json');
echo $json->encode($return);
}
}
+221
View File
@@ -0,0 +1,221 @@
<?php
/**
* Move Plugin Page Rename Functionality
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class action_plugin_move_rename
*/
class action_plugin_move_rename extends DokuWiki_Action_Plugin {
/**
* Register event handlers.
*
* @param Doku_Event_Handler $controller The plugin controller
*/
public function register(Doku_Event_Handler $controller) {
$controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'handle_init');
// TODO: DEPRECATED JAN 2018
$controller->register_hook('TEMPLATE_PAGETOOLS_DISPLAY', 'BEFORE', $this, 'handle_pagetools');
$controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'addsvgbutton', array());
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax');
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxMediaManager');
}
/**
* set JavaScript info if renaming of current page is possible
*/
public function handle_init() {
global $JSINFO;
global $INFO;
global $INPUT;
global $USERINFO;
if (isset($INFO['id'])) {
$JSINFO['move_renameokay'] = $this->renameOkay($INFO['id']);
} else {
$JSINFO['move_renameokay'] = false;
}
$JSINFO['move_allowrename'] = auth_isMember(
$this->getConf('allowrename'),
$INPUT->server->str('REMOTE_USER'),
$USERINFO['grps'] ?? []
);
}
/**
* Adds a button to the default template
*
* TODO: DEPRECATED JAN 2018
*
* @param Doku_Event $event
*/
public function handle_pagetools(Doku_Event $event) {
if($event->data['view'] != 'main') return;
if (!$this->getConf('pagetools_integration')) {
return;
}
$newitem = '<li class="plugin_move_page"><a href=""><span>' . $this->getLang('renamepage') . '</span></a></li>';
$offset = count($event->data['items']) - 1;
$event->data['items'] =
array_slice($event->data['items'], 0, $offset, true) +
array('plugin_move' => $newitem) +
array_slice($event->data['items'], $offset, null, true);
}
/**
* Add 'rename' button to page tools, new SVG based mechanism
*
* @param Doku_Event $event
*/
public function addsvgbutton(Doku_Event $event) {
global $INFO, $JSINFO;
if(
$event->data['view'] !== 'page' ||
!$this->getConf('pagetools_integration') ||
empty($JSINFO['move_renameokay'])
) {
return;
}
if(!$INFO['exists']) {
return;
}
array_splice($event->data['items'], -1, 0, array(new \dokuwiki\plugin\move\MenuItem()));
}
/**
* Rename a single page
*/
public function handle_ajax(Doku_Event $event) {
if($event->data != 'plugin_move_rename') return;
$event->preventDefault();
$event->stopPropagation();
global $MSG;
global $INPUT;
$src = cleanID($INPUT->str('id'));
$dst = cleanID($INPUT->str('newid'));
/** @var helper_plugin_move_op $MoveOperator */
$MoveOperator = plugin_load('helper', 'move_op');
$JSON = new JSON();
header('Content-Type: application/json');
if($this->renameOkay($src) && $MoveOperator->movePage($src, $dst)) {
// all went well, redirect
echo $JSON->encode(array('redirect_url' => wl($dst, '', true, '&')));
} else {
if(isset($MSG[0])) {
$error = $MSG[0]; // first error
} else {
$error = $this->getLang('cantrename');
}
echo $JSON->encode(array('error' => $error));
}
}
/**
* Handle media renames in media manager
*
* @param Doku_Event $event
* @return void
*/
public function handleAjaxMediaManager(Doku_Event $event)
{
if ($event->data !== 'plugin_move_rename_mediamanager') return;
if (!checkSecurityToken()) {
throw new \Exception('Security token did not match');
}
$event->preventDefault();
$event->stopPropagation();
global $INPUT;
global $MSG;
global $USERINFO;
$src = cleanID($INPUT->str('src'));
$dst = cleanID($INPUT->str('dst'));
/** @var helper_plugin_move_op $moveOperator */
$moveOperator = plugin_load('helper', 'move_op');
if ($src && $dst) {
header('Content-Type: application/json');
$response = [];
// check user/group restrictions
if (
!auth_isMember($this->getConf('allowrename'), $INPUT->server->str('REMOTE_USER'), (array) $USERINFO['grps'])
) {
$response['error'] = $this->getLang('notallowed');
echo json_encode($response);
return;
}
$response['success'] = $moveOperator->moveMedia($src, $dst);
if ($response['success']) {
$ns = getNS($dst);
$response['redirect_url'] = wl($dst, ['do' => 'media', 'ns' => $ns], true, '&');
} else {
$response['error'] = sprintf($this->getLang('mediamoveerror'), $src);
if (isset($MSG)) {
foreach ($MSG as $msg) {
$response['error'] .= ' ' . $msg['msg'];
}
}
}
echo json_encode($response);
}
}
/**
* Determines if it would be okay to show a rename page button for the given page and current user
*
* @param $id
* @return bool
*/
public function renameOkay($id) {
global $conf;
global $ACT;
global $USERINFO;
if(!($ACT == 'show' || empty($ACT))) return false;
if(!page_exists($id)) return false;
if(auth_quickaclcheck($id) < AUTH_EDIT) return false;
if(checklock($id) !== false || @file_exists(wikiLockFN($id))) return false;
if(!$conf['useacl']) return true;
if(!isset($_SERVER['REMOTE_USER'])) return false;
if(!auth_isMember($this->getConf('allowrename'), $_SERVER['REMOTE_USER'], (array) $USERINFO['grps'])) return false;
return true;
}
/**
* Use this in your template to add a simple "move this page" link
*
* Alternatively give anything the class "plugin_move_page" - it will automatically be hidden and shown and
* trigger the page move dialog.
*/
public function tpl() {
echo '<a href="" class="plugin_move_page">';
echo $this->getLang('renamepage');
echo '</a>';
}
}
+112
View File
@@ -0,0 +1,112 @@
<?php
/**
* Move Plugin Page Rewrite Functionality
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class action_plugin_move_rewrite
*/
class action_plugin_move_rewrite extends DokuWiki_Action_Plugin {
/**
* Register event handlers.
*
* @param Doku_Event_Handler $controller The plugin controller
*/
public function register(Doku_Event_Handler $controller) {
$controller->register_hook('IO_WIKIPAGE_READ', 'AFTER', $this, 'handle_read', array());
$controller->register_hook('PARSER_CACHE_USE', 'BEFORE', $this, 'handle_cache', array());
}
/**
* Rewrite pages when they are read and they need to be updated.
*
* @param Doku_Event $event The event object
* @param mixed $param Optional parameters (not used)
*/
function handle_read(Doku_Event $event, $param) {
global $ACT, $conf;
static $stack = array();
// handle only reads of the current revision
if($event->data[3]) return;
// only rewrite if not in move already
$save = true;
if(helper_plugin_move_rewrite::isLocked()) {
$save = false;
}
$id = $event->data[2];
if($event->data[1]) $id = $event->data[1] . ':' . $id;
if(!$id) {
// try to reconstruct the id from the filename
$path = $event->data[0][0];
if(strpos($path, $conf['datadir']) === 0) {
$path = substr($path, strlen($conf['datadir']) + 1);
$id = pathID($path);
}
}
if(isset($stack[$id])) return;
// Don't change the page when the user is currently changing the page content or the page is locked
$forbidden_actions = array('save', 'preview', 'recover', 'revert');
if((isset($ACT) && (
in_array($ACT, $forbidden_actions) || (is_array($ACT) && in_array(key($ACT), $forbidden_actions)
)))
// checklock checks if the page lock hasn't expired and the page hasn't been locked by another user
// the file exists check checks if the page is reported unlocked if a lock exists which means that
// the page is locked by the current user
|| checklock($id) !== false || @file_exists(wikiLockFN($id))
) return;
/** @var helper_plugin_move_rewrite $helper */
$helper = plugin_load('helper', 'move_rewrite', true);
if(!is_null($helper)) {
$stack[$id] = true;
$event->result = $helper->rewritePage($id, $event->result, $save);
unset($stack[$id]);
}
}
/**
* Handle the cache events, it looks if a page needs to be rewritten so it can expire the cache of the page
*
* @param Doku_Event $event The even object
* @param mixed $param Optional parameters (not used)
*/
function handle_cache(Doku_Event $event, $param) {
global $conf;
/** @var $cache cache_parser */
$cache = $event->data;
$id = $cache->page;
if(!$id) {
// try to reconstruct the id from the filename
$path = $cache->file;
if(strpos($path, $conf['datadir']) === 0) {
$path = substr($path, strlen($conf['datadir']) + 1);
$id = pathID($path);
}
}
if($id) {
/** @var helper_plugin_move_rewrite $helper */
$helper = $this->loadHelper('move_rewrite');
if(!is_null($helper)) {
$meta = $helper->getMoveMeta($id);
if($meta && ($meta['pages'] || $meta['media'])) {
$file = wikiFN($id, '', false);
if(is_writable($file))
$cache->depends['purge'] = true;
else // FIXME: print error here or fail silently?
msg('Error: Page ' . hsc($id) . ' needs to be rewritten because of page renames but is not writable.', -1);
}
}
}
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
/**
* Move Plugin Tree Loading Functionality
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class action_plugin_move_rewrite
*/
class action_plugin_move_tree extends DokuWiki_Action_Plugin {
/**
* Register event handlers.
*
* @param Doku_Event_Handler $controller The plugin controller
*/
public function register(Doku_Event_Handler $controller) {
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handle_ajax_call');
}
/**
* Render a subtree
*
* @param Doku_Event $event
* @param $params
*/
public function handle_ajax_call(Doku_Event $event, $params) {
if($event->data != 'plugin_move_tree') return;
$event->preventDefault();
$event->stopPropagation();
global $INPUT;
global $USERINFO;
if(!auth_ismanager($_SERVER['REMOTE_USER'], $USERINFO['grps'])) {
http_status(403);
exit;
}
/** @var admin_plugin_move_tree $plugin */
$plugin = plugin_load('admin', 'move_tree');
$ns = cleanID($INPUT->str('ns'));
if($INPUT->bool('is_media')) {
$type = admin_plugin_move_tree::TYPE_MEDIA;
} else {
$type = admin_plugin_move_tree::TYPE_PAGES;
}
$data = $plugin->tree($type, $ns, $ns);
echo html_buildlist(
$data, 'tree_list',
array($plugin, 'html_list'),
array($plugin, 'html_li')
);
}
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M18,4V3A1,1 0 0,0 17,2H5A1,1 0 0,0 4,3V7A1,1 0 0,0 5,8H17A1,1 0 0,0 18,7V6H19V10H9V21A1,1 0 0,0 10,22H12A1,1 0 0,0 13,21V12H21V4H18Z" /></svg>

After

Width:  |  Height:  |  Size: 235 B

+270
View File
@@ -0,0 +1,270 @@
<?php
/**
* Plugin : Move
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
* @author Gary Owen,
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Admin component of the move plugin. Provides the user interface.
*/
class admin_plugin_move_main extends DokuWiki_Admin_Plugin {
/** @var helper_plugin_move_plan $plan */
protected $plan;
public function __construct() {
$this->plan = plugin_load('helper', 'move_plan');
}
/**
* @param $language
* @return string
*/
public function getMenuText($language) {
$label = $this->getLang('menu');
if($this->plan->isCommited()) $label .= ' '.$this->getLang('inprogress');
return $label;
}
/**
* Get the sort number that defines the position in the admin menu.
*
* @return int The sort number
*/
function getMenuSort() {
return 1011;
}
/**
* If this admin plugin is for admins only
*
* @return bool false
*/
function forAdminOnly() {
return false;
}
/**
* Handle the input
*/
function handle() {
global $INPUT;
// create a new plan if possible and sufficient data was given
$this->createPlanFromInput();
// handle workflow button presses
if($this->plan->isCommited()) {
helper_plugin_move_rewrite::addLock(); //todo: right place?
switch($INPUT->str('ctl')) {
case 'continue':
$this->plan->nextStep();
break;
case 'skip':
$this->plan->nextStep(true);
break;
case 'abort':
$this->plan->abort();
break;
}
}
}
/**
* Display the interface
*/
function html() {
// decide what to do based on the plan's state
if($this->plan->isCommited()) {
$this->GUI_progress();
} else {
// display form
$this->GUI_simpleForm();
}
}
/**
* Get input variables and create a move plan from them
*
* @return bool
*/
protected function createPlanFromInput() {
global $INPUT;
global $ID;
if($this->plan->isCommited()) return false;
$this->plan->setOption('autoskip', $INPUT->bool('autoskip'));
$this->plan->setOption('autorewrite', $INPUT->bool('autorewrite'));
if($ID && $INPUT->has('dst')) {
$dst = trim($INPUT->str('dst'));
if($dst == '') {
msg($this->getLang('nodst'), -1);
return false;
}
// input came from form
if($INPUT->str('class') == 'namespace') {
$src = getNS($ID);
if($INPUT->str('type') == 'both') {
$this->plan->addPageNamespaceMove($src, $dst);
$this->plan->addMediaNamespaceMove($src, $dst);
} else if($INPUT->str('type') == 'page') {
$this->plan->addPageNamespaceMove($src, $dst);
} else if($INPUT->str('type') == 'media') {
$this->plan->addMediaNamespaceMove($src, $dst);
}
} else {
$this->plan->addPageMove($ID, $INPUT->str('dst'));
}
$this->plan->commit();
return true;
} elseif($INPUT->has('json')) {
// input came via JSON from tree manager
$json = new JSON(JSON_LOOSE_TYPE);
$data = $json->decode($INPUT->str('json'));
foreach((array) $data as $entry) {
if($entry['class'] == 'ns') {
if($entry['type'] == 'page') {
$this->plan->addPageNamespaceMove($entry['src'], $entry['dst']);
} elseif($entry['type'] == 'media') {
$this->plan->addMediaNamespaceMove($entry['src'], $entry['dst']);
}
} elseif($entry['class'] == 'doc') {
if($entry['type'] == 'page') {
$this->plan->addPageMove($entry['src'], $entry['dst']);
} elseif($entry['type'] == 'media') {
$this->plan->addMediaMove($entry['src'], $entry['dst']);
}
}
}
$this->plan->commit();
return true;
}
return false;
}
/**
* Display the simple move form
*/
protected function GUI_simpleForm() {
global $ID;
echo $this->locale_xhtml('move');
$treelink = wl($ID, array('do'=>'admin', 'page'=>'move_tree'));
echo '<p id="plugin_move__treelink">';
printf($this->getLang('treelink'), $treelink);
echo '</p>';
$form = new Doku_Form(array('action' => wl($ID), 'method' => 'post', 'class' => 'plugin_move_form'));
$form->addHidden('page', 'move_main');
$form->addHidden('id', $ID);
$form->startFieldset($this->getLang('legend'));
$form->addElement(form_makeRadioField('class', 'page', $this->getLang('movepage') . ' <code>' . $ID . '</code>', '', 'block radio click-page', array('checked' => 'checked')));
$form->addElement(form_makeRadioField('class', 'namespace', $this->getLang('movens') . ' <code>' . getNS($ID) . '</code>', '', 'block radio click-ns'));
$form->addElement(form_makeTextField('dst', $ID, $this->getLang('dst'), '', 'block indent'));
$form->addElement(form_makeMenuField('type', array('pages' => $this->getLang('move_pages'), 'media' => $this->getLang('move_media'), 'both' => $this->getLang('move_media_and_pages')), 'both', $this->getLang('content_to_move'), '', 'block indent select'));
$form->addElement(form_makeCheckboxField('autoskip', '1', $this->getLang('autoskip'), '', 'block', ($this->getConf('autoskip') ? array('checked' => 'checked') : array())));
$form->addElement(form_makeCheckboxField('autorewrite', '1', $this->getLang('autorewrite'), '', 'block', ($this->getConf('autorewrite') ? array('checked' => 'checked') : array())));
$form->addElement(form_makeButton('submit', 'admin', $this->getLang('btn_start')));
$form->endFieldset();
$form->printForm();
}
/**
* Display the GUI while the move progresses
*/
protected function GUI_progress() {
echo '<div id="plugin_move__progress">';
echo $this->locale_xhtml('progress');
$progress = $this->plan->getProgress();
if(!$this->plan->inProgress()) {
echo '<div id="plugin_move__preview">';
echo '<p>';
echo '<strong>' . $this->getLang('intro') . '</strong> ';
echo '<span>' . $this->getLang('preview') . '</span>';
echo '</p>';
echo $this->plan->previewHTML();
echo '</div>';
}
echo '<div class="progress" data-progress="' . $progress . '">' . $progress . '%</div>';
echo '<div class="output">';
if($this->plan->getLastError()) {
echo '<p><div class="error">' . $this->plan->getLastError() . '</div></p>';
} elseif ($this->plan->inProgress()) {
echo '<p><div class="info">' . $this->getLang('inexecution') . '</div></p>';
}
echo '</div>';
// display all buttons but toggle visibility according to state
echo '<p></p>';
echo '<div class="controls">';
echo '<img src="' . DOKU_BASE . 'lib/images/throbber.gif" class="hide" />';
$this->btn('start', !$this->plan->inProgress());
$this->btn('retry', $this->plan->getLastError());
$this->btn('skip', $this->plan->getLastError());
$this->btn('continue', $this->plan->inProgress() && !$this->plan->getLastError());
$this->btn('abort');
echo '</div>';
echo '</div>';
}
/**
* Display a move workflow button
*
* continue, start, retry - continue next steps
* abort - abort the whole move
* skip - skip error and continue
*
* @param string $control
* @param bool $show should this control be visible?
*/
protected function btn($control, $show = true) {
global $ID;
$skip = 0;
$label = $this->getLang('btn_' . $control);
$id = $control;
if($control == 'start') $control = 'continue';
if($control == 'retry') {
$control = 'continue';
$skip = 0;
}
$class = 'move__control ctlfrm-' . $id;
if(!$show) $class .= ' hide';
$form = new Doku_Form(array('action' => wl($ID), 'method' => 'post', 'class' => $class));
$form->addHidden('page', 'move_main');
$form->addHidden('id', $ID);
$form->addHidden('ctl', $control);
$form->addHidden('skip', $skip);
$form->addElement(form_makeButton('submit', 'admin', $label, array('class' => 'btn ctl-' . $control)));
$form->printForm();
}
}
+189
View File
@@ -0,0 +1,189 @@
<?php
class admin_plugin_move_tree extends DokuWiki_Admin_Plugin {
const TYPE_PAGES = 1;
const TYPE_MEDIA = 2;
/**
* @param $language
* @return bool
*/
public function getMenuText($language) {
return false; // do not show in Admin menu
}
/**
* If this admin plugin is for admins only
*
* @return bool false
*/
function forAdminOnly() {
return false;
}
/**
* no-op
*/
public function handle() {
}
public function html() {
global $ID;
echo $this->locale_xhtml('tree');
echo '<noscript><div class="error">' . $this->getLang('noscript') . '</div></noscript>';
echo '<div id="plugin_move__tree">';
echo '<div class="tree_root tree_pages">';
echo '<h3>' . $this->getLang('move_pages') . '</h3>';
$this->htmlTree(self::TYPE_PAGES);
echo '</div>';
echo '<div class="tree_root tree_media">';
echo '<h3>' . $this->getLang('move_media') . '</h3>';
$this->htmlTree(self::TYPE_MEDIA);
echo '</div>';
/** @var helper_plugin_move_plan $plan */
$plan = plugin_load('helper', 'move_plan');
echo '<div class="controls">';
if($plan->isCommited()) {
echo '<div class="error">' . $this->getLang('moveinprogress') . '</div>';
} else {
$form = new Doku_Form(array('action' => wl($ID), 'id' => 'plugin_move__tree_execute'));
$form->addHidden('id', $ID);
$form->addHidden('page', 'move_main');
$form->addHidden('json', '');
$form->addElement(form_makeCheckboxField('autoskip', '1', $this->getLang('autoskip'), '', '', ($this->getConf('autoskip') ? array('checked' => 'checked') : array())));
$form->addElement('<br />');
$form->addElement(form_makeCheckboxField('autorewrite', '1', $this->getLang('autorewrite'), '', '', ($this->getConf('autorewrite') ? array('checked' => 'checked') : array())));
$form->addElement('<br />');
$form->addElement('<br />');
$form->addElement(form_makeButton('submit', 'admin', $this->getLang('btn_start')));
$form->printForm();
}
echo '</div>';
echo '</div>';
}
/**
* print the HTML tree structure
*
* @param int $type
*/
protected function htmlTree($type = self::TYPE_PAGES) {
$data = $this->tree($type);
// wrap a list with the root level around the other namespaces
array_unshift(
$data, array(
'level' => 0, 'id' => '*', 'type' => 'd',
'open' => 'true', 'label' => $this->getLang('root')
)
);
echo html_buildlist(
$data, 'tree_list idx',
array($this, 'html_list'),
array($this, 'html_li')
);
}
/**
* Build a tree info structure from media or page directories
*
* @param int $type
* @param string $open The hierarchy to open FIXME not supported yet
* @param string $base The namespace to start from
* @return array
*/
public function tree($type = self::TYPE_PAGES, $open = '', $base = '') {
global $conf;
$opendir = utf8_encodeFN(str_replace(':', '/', $open));
$basedir = utf8_encodeFN(str_replace(':', '/', $base));
$opts = array(
'pagesonly' => ($type == self::TYPE_PAGES),
'listdirs' => true,
'listfiles' => true,
'sneakyacl' => $conf['sneaky_index'],
'showmsg' => false,
'depth' => 1,
'showhidden' => true
);
$data = array();
if($type == self::TYPE_PAGES) {
search($data, $conf['datadir'], 'search_universal', $opts, $basedir);
} elseif($type == self::TYPE_MEDIA) {
search($data, $conf['mediadir'], 'search_universal', $opts, $basedir);
}
return $data;
}
/**
* Item formatter for the tree view
*
* User function for html_buildlist()
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function html_list($item) {
$ret = '';
// what to display
if(!empty($item['label'])) {
$base = $item['label'];
} else {
$base = ':' . $item['id'];
$base = substr($base, strrpos($base, ':') + 1);
}
if($item['id'] == '*') $item['id'] = '';
if ($item['id']) {
$ret .= '<input type="checkbox" /> ';
}
// namespace or page?
if($item['type'] == 'd') {
$ret .= '<a href="' . $item['id'] . '" class="idx_dir">';
$ret .= $base;
$ret .= '</a>';
} else {
$ret .= '<a class="wikilink1">';
$ret .= noNS($item['id']);
$ret .= '</a>';
}
if($item['id']) $ret .= '<img class="rename" src="'. DOKU_BASE .'lib/plugins/move/images/rename.png" />';
else $ret .= '<img class="add" src="' . DOKU_BASE . 'lib/plugins/move/images/folder_add.png" />';
return $ret;
}
/**
* print the opening LI for a list item
*
* @param array $item
* @return string
*/
function html_li($item) {
if($item['id'] == '*') $item['id'] = '';
$params = array();
$params['class'] = ' type-' . $item['type'];
if($item['type'] == 'd') $params['class'] .= ' ' . ($item['open'] ? 'open' : 'closed');
$params['data-name'] = noNS($item['id']);
$params['data-id'] = $item['id'];
$attr = buildAttributes($params);
return "<li $attr>";
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
$conf['allowrename'] = '@user';
$conf['minor'] = 1;
$conf['autoskip'] = 0;
$conf['autorewrite'] = 1;
$conf['pagetools_integration'] = 1;
+7
View File
@@ -0,0 +1,7 @@
<?php
$meta['allowrename'] = array('string');
$meta['minor'] = array('onoff');
$meta['autoskip'] = array('onoff');
$meta['autorewrite'] = array('onoff');
$meta['pagetools_integration'] = array('onoff');
+34
View File
@@ -0,0 +1,34 @@
# This is a list of files that were present in previous plugin releases
# but were removed later. An up to date plugin should not have any of
# the files installed
_action.php
action.php
admin.php
helper.php
rename.png
sprite.png
_test/plugin_move_cache_handling.test.php
_test/mediaindex.test.php
helper/general.php
admin/simple.php
script/move.js
lang/cs/pagemove.txt
lang/de/pagemove.txt
lang/en/pagemove.txt
lang/es/pagemove.txt
lang/fr/pagemove.txt
lang/lv/pagemove.txt
lang/nl/pagemove.txt
lang/pl/pagemove.txt
lang/ru/pagemove.txt
lang/sl/pagemove.txt
lang/cs/lang.php.txt
lang/cs/pagemove.txt.txt
lang/es/lang.php.txt
lang/es/pagemove.txt.txt
lang/pl/lang.php.txt
lang/pl/pagemove.txt.txt
lang/zh/pagemove.txt
.travis.yml
+156
View File
@@ -0,0 +1,156 @@
<?php
/**
* Move Plugin File Mover
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class helper_plugin_move_file
*
* This helps with moving files from one folder to another. It simply matches files and moves them
* arround. No fancy rewriting happens here.
*/
class helper_plugin_move_file extends DokuWiki_Plugin {
/**
* Move the meta files of a page
*
* @param string $src_ns The original namespace
* @param string $src_name The original basename of the moved doc (empty for namespace moves)
* @param string $dst_ns The namespace after the move
* @param string $dst_name The basename after the move (empty for namespace moves)
* @return bool If the meta files were moved successfully
*/
public function movePageMeta($src_ns, $src_name, $dst_ns, $dst_name) {
global $conf;
$regex = '\.[^.]+';
return $this->execute($conf['metadir'], $src_ns, $src_name, $dst_ns, $dst_name, $regex);
}
/**
* Move the old revisions of a page
*
* @param string $src_ns The original namespace
* @param string $src_name The original basename of the moved doc (empty for namespace moves)
* @param string $dst_ns The namespace after the move
* @param string $dst_name The basename after the move (empty for namespace moves)
* @return bool If the attic files were moved successfully
*/
public function movePageAttic($src_ns, $src_name, $dst_ns, $dst_name) {
global $conf;
$regex = '\.\d+\.txt(?:\.gz|\.bz2)?';
return $this->execute($conf['olddir'], $src_ns, $src_name, $dst_ns, $dst_name, $regex);
}
/**
* Move the meta files of the page that is specified in the options.
*
* @param string $src_ns The original namespace
* @param string $src_name The original basename of the moved doc (empty for namespace moves)
* @param string $dst_ns The namespace after the move
* @param string $dst_name The basename after the move (empty for namespace moves)
* @return bool If the meta files were moved successfully
*/
public function moveMediaMeta($src_ns, $src_name, $dst_ns, $dst_name) {
global $conf;
$regex = '\.[^.]+';
return $this->execute($conf['mediametadir'], $src_ns, $src_name, $dst_ns, $dst_name, $regex);
}
/**
* Move the old revisions of the media file that is specified in the options
*
* @param string $src_ns The original namespace
* @param string $src_name The original basename of the moved doc (empty for namespace moves)
* @param string $dst_ns The namespace after the move
* @param string $dst_name The basename after the move (empty for namespace moves)
* @return bool If the attic files were moved successfully
*/
public function moveMediaAttic($src_ns, $src_name, $dst_ns, $dst_name) {
global $conf;
$ext = mimetype($src_name);
if($ext[0] !== false) {
$name = substr($src_name, 0, -1 * strlen($ext[0]) - 1);
} else {
$name = $src_name;
}
$newext = mimetype($dst_name);
if($newext[0] !== false) {
$newname = substr($dst_name, 0, -1 * strlen($newext[0]) - 1);
} else {
$newname = $dst_name;
}
$regex = '\.\d+\.' . preg_quote((string) $ext[0], '/');
return $this->execute($conf['mediaolddir'], $src_ns, $name, $dst_ns, $newname, $regex);
}
/**
* Moves the subscription file for a namespace
*
* @param string $src_ns
* @param string $dst_ns
* @return bool
*/
public function moveNamespaceSubscription($src_ns, $dst_ns){
global $conf;
$regex = '\.mlist';
return $this->execute($conf['metadir'], $src_ns, '', $dst_ns, '', $regex);
}
/**
* Executes the move op
*
* @param string $dir The root path of the files (e.g. $conf['metadir'] or $conf['olddir']
* @param string $src_ns The original namespace
* @param string $src_name The original basename of the moved doc (empty for namespace moves)
* @param string $dst_ns The namespace after the move
* @param string $dst_name The basename after the move (empty for namespace moves)
* @param string $extregex Regular expression for matching the extension of the file that shall be moved
* @return bool If the files were moved successfully
*/
protected function execute($dir, $src_ns, $src_name, $dst_ns, $dst_name, $extregex) {
$old_path = $dir;
if($src_ns != '') $old_path .= '/' . utf8_encodeFN(str_replace(':', '/', $src_ns));
$new_path = $dir;
if($dst_ns != '') $new_path .= '/' . utf8_encodeFN(str_replace(':', '/', $dst_ns));
$regex = '/^' . preg_quote(utf8_encodeFN($src_name)) . '(' . $extregex . ')$/u';
if(!is_dir($old_path)) return true; // no media files found
$dh = @opendir($old_path);
if($dh) {
while(($file = readdir($dh)) !== false) {
if($file == '.' || $file == '..') continue;
$match = array();
if(is_file($old_path . '/' . $file) && preg_match($regex, $file, $match)) {
if(!is_dir($new_path)) {
if(!io_mkdir_p($new_path)) {
msg('Creating directory ' . hsc($new_path) . ' failed.', -1);
return false;
}
}
if(!io_rename($old_path . '/' . $file, $new_path . '/' . utf8_encodeFN($dst_name . $match[1]))) {
msg('Moving ' . hsc($old_path . '/' . $file) . ' to ' . hsc($new_path . '/' . utf8_encodeFN($dst_name . $match[1])) . ' failed.', -1);
return false;
}
}
}
closedir($dh);
} else {
msg('Directory ' . hsc($old_path) . ' couldn\'t be opened.', -1);
return false;
}
return true;
}
}
+387
View File
@@ -0,0 +1,387 @@
<?php
/**
* Move Plugin Rewriting Handler
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Handler class for move. It does the actual rewriting of the content.
*
* Note: This is not actually a valid DokuWiki Helper plugin and can not be loaded via plugin_load()
*/
class helper_plugin_move_handler extends DokuWiki_Plugin {
public $calls = '';
protected $id;
protected $ns;
protected $origID;
protected $origNS;
protected $page_moves;
protected $media_moves;
protected $handlers;
/**
* Do not allow re-using instances.
*
* @return bool false - the handler must not be re-used.
*/
public function isSingleton() {
return false;
}
/**
* Initialize the move handler.
*
* @param string $id The id of the text that is passed to the handler
* @param string $original The name of the original ID of this page. Same as $id if this page wasn't moved
* @param array $page_moves Moves that shall be considered in the form [[$old,$new],...] ($old can be $original)
* @param array $media_moves Moves of media files that shall be considered in the form $old => $new
* @param array $handlers Handlers for plugin content in the form $plugin_name => $callback
*/
public function init($id, $original, $page_moves, $media_moves, $handlers) {
$this->id = $id;
$this->ns = getNS($id);
$this->origID = $original;
$this->origNS = getNS($original);
$this->page_moves = $page_moves;
$this->media_moves = $media_moves;
$this->handlers = $handlers;
}
/**
* Go through the list of moves and find the new value for the given old ID
*
* @param string $old the old, full qualified ID
* @param string $type 'media' or 'page'
* @throws Exception on bad argument
* @return string the new full qualified ID
*/
public function resolveMoves($old, $type) {
global $conf;
if($type != 'media' && $type != 'page') throw new Exception('Not a valid type');
$old = resolve_id($this->origNS, $old, false);
if($type == 'page') {
// FIXME this simply assumes that the link pointed to :$conf['start'], but it could also point to another page
// resolve_pageid does a lot more here, but we can't really assume this as the original pages might have been
// deleted already
if(substr($old, -1) === ':' || $old === '') $old .= $conf['start'];
$moves = $this->page_moves;
} else {
$moves = $this->media_moves;
}
$old = cleanID($old);
foreach($moves as $move) {
if($move[0] == $old) {
$old = $move[1];
}
}
return $old; // this is now new
}
/**
* if the old link ended with a colon and the new one is a start page, adjust
*
* @param $relold string the old, possibly relative ID
* @param $new string the new, full qualified ID
* @param $type 'media' or 'page'
* @return string
*/
protected function _nsStartCheck($relold, $new, $type) {
global $conf;
if($type == 'page' && substr($relold, -1) == ':') {
$len = strlen($conf['start']);
if($new == $conf['start']) {
$new = '.:';
} else if(substr($new, -1 * ($len + 1)) == ':' . $conf['start']) {
$new = substr($new, 0, -1 * $len);
}
}
return $new;
}
/**
* Construct a new ID relative to the current page's location
*
* Uses a relative link only if the original was relative, too. This function is for
* pages and media files.
*
* @param string $relold the old, possibly relative ID
* @param string $new the new, full qualified ID
* @param string $type 'media' or 'page'
* @throws Exception on bad argument
* @return string
*/
public function relativeLink($relold, $new, $type) {
global $conf;
if($type != 'media' && $type != 'page') throw new Exception('Not a valid type');
// first check if the old link still resolves
$exists = false;
$old = $relold;
if($type == 'page') {
resolve_pageid($this->ns, $old, $exists);
// Work around bug in DokuWiki 2020-07-29 where resolve_pageid doesn't append the start page to a link to
// the root.
if ($old === '') {
$old = $conf['start'];
}
} else {
resolve_mediaid($this->ns, $old, $exists);
}
if($old == $new) {
return $relold; // old link still resolves, keep as is
}
if($conf['useslash']) $relold = str_replace('/', ':', $relold);
// check if the link was relative
if(strpos($relold, ':') === false ||$relold[0] == '.') {
$wasrel = true;
} else {
$wasrel = false;
}
// if it wasn't relative then, leave it absolute now, too
if(!$wasrel) {
if($this->ns && !getNS($new)) $new = ':' . $new;
$new = $this->_nsStartCheck($relold, $new, $type);
return $new;
}
// split the paths and see how much common parts there are
$selfpath = explode(':', $this->ns);
$goalpath = explode(':', getNS($new));
$min = min(count($selfpath), count($goalpath));
for($common = 0; $common < $min; $common++) {
if($selfpath[$common] != $goalpath[$common]) break;
}
// we now have the non-common part and a number of uppers
$ups = max(count($selfpath) - $common, 0);
$remainder = array_slice($goalpath, $common);
$upper = $ups ? array_fill(0, $ups, '..:') : array();
// build the new relative path
$newrel = join(':', $upper);
if($remainder) $newrel .= join(':', $remainder) . ':';
$newrel .= noNS($new);
$newrel = str_replace('::', ':', trim($newrel, ':'));
if($newrel[0] != '.' && $this->ns && getNS($newrel)) $newrel = '.' . $newrel;
// if the old link ended with a colon and the new one is a start page, adjust
$newrel = $this->_nsStartCheck($relold,$newrel,$type);
// don't use relative paths if it is ridicoulus:
if(strlen($newrel) > strlen($new)) {
$newrel = $new;
if($this->ns && !getNS($new)) $newrel = ':' . $newrel;
$newrel = $this->_nsStartCheck($relold,$newrel,$type);
}
return $newrel;
}
/**
* Handle camelcase links
*
* @param string $match The text match
* @param string $state The starte of the parser
* @param int $pos The position in the input
* @return bool If parsing should be continued
*/
public function camelcaselink($match, $state, $pos) {
$oldID = cleanID($this->origNS . ':' . $match);
$newID = $this->resolveMoves($oldID, 'page');
$newNS = getNS($newID);
if($oldID == $newID || $this->origNS == $newNS) {
// link is still valid as is
$this->calls .= $match;
} else {
if(noNS($oldID) == noNS($newID)) {
// only namespace changed, keep CamelCase in link
$this->calls .= "[[$newNS:$match]]";
} else {
// all new, keep CamelCase in title
$this->calls .= "[[$newID|$match]]";
}
}
return true;
}
/**
* Handle rewriting of internal links
*
* @param string $match The text match
* @param string $state The starte of the parser
* @param int $pos The position in the input
* @return bool If parsing should be continued
*/
public function internallink($match, $state, $pos) {
// Strip the opening and closing markup
$link = preg_replace(array('/^\[\[/', '/\]\]$/u'), '', $match);
// Split title from URL
$link = explode('|', $link, 2);
if(!isset($link[1])) {
$link[1] = null;
} else if(preg_match('/^\{\{[^\}]+\}\}$/', $link[1])) {
// If the title is an image, rewrite it
$old_title = $link[1];
$link[1] = $this->rewrite_media($link[1]);
// do a simple replace of the first match so really only the id is changed and not e.g. the alignment
$oldpos = strpos($match, $old_title);
$oldlen = strlen($old_title);
$match = substr_replace($match, $link[1], $oldpos, $oldlen);
}
$link[0] = trim($link[0]);
//decide which kind of link it is
if(preg_match('/^[a-zA-Z0-9\.]+>{1}.*$/u', $link[0])) {
// Interwiki
$this->calls .= $match;
} elseif(preg_match('/^\\\\\\\\[^\\\\]+?\\\\/u', $link[0])) {
// Windows Share
$this->calls .= $match;
} elseif(preg_match('#^([a-z0-9\-\.+]+?)://#i', $link[0])) {
// external link (accepts all protocols)
$this->calls .= $match;
} elseif(preg_match('<' . PREG_PATTERN_VALID_EMAIL . '>', $link[0])) {
// E-Mail (pattern above is defined in inc/mail.php)
$this->calls .= $match;
} elseif(preg_match('!^#.+!', $link[0])) {
// local hash link
$this->calls .= $match;
} else {
$id = $link[0];
$hash = '';
$parts = explode('#', $id, 2);
if(count($parts) === 2) {
$id = $parts[0];
$hash = $parts[1];
}
$params = '';
$parts = explode('?', $id, 2);
if(count($parts) === 2) {
$id = $parts[0];
$params = $parts[1];
}
$new_id = $this->resolveMoves($id, 'page');
$new_id = $this->relativeLink($id, $new_id, 'page');
if($id == $new_id) {
$this->calls .= $match;
} else {
if($params !== '') {
$new_id .= '?' . $params;
}
if($hash !== '') {
$new_id .= '#' . $hash;
}
if($link[1] != null) {
$new_id .= '|' . $link[1];
}
$this->calls .= '[[' . $new_id . ']]';
}
}
return true;
}
/**
* Handle rewriting of media links
*
* @param string $match The text match
* @param string $state The starte of the parser
* @param int $pos The position in the input
* @return bool If parsing should be continued
*/
public function media($match, $state, $pos) {
$this->calls .= $this->rewrite_media($match);
return true;
}
/**
* Rewrite a media syntax
*
* @param string $match The text match of the media syntax
* @return string The rewritten syntax
*/
protected function rewrite_media($match) {
$p = Doku_Handler_Parse_Media($match);
if($p['type'] == 'internalmedia') { // else: external media
$new_src = $this->resolveMoves($p['src'], 'media');
$new_src = $this->relativeLink($p['src'], $new_src, 'media');
if($new_src !== $p['src']) {
// do a simple replace of the first match so really only the id is changed and not e.g. the alignment
$srcpos = strpos($match, $p['src']);
$srclen = strlen($p['src']);
return substr_replace($match, $new_src, $srcpos, $srclen);
}
}
return $match;
}
/**
* Handle rewriting of plugin syntax, calls the registered handlers
*
* @param string $match The text match
* @param string $state The starte of the parser
* @param int $pos The position in the input
* @param string $pluginname The name of the plugin
* @return bool If parsing should be continued
*/
public function plugin($match, $state, $pos, $pluginname) {
if(isset($this->handlers[$pluginname])) {
$this->calls .= call_user_func($this->handlers[$pluginname], $match, $state, $pos, $pluginname, $this);
} else {
$this->calls .= $match;
}
return true;
}
/**
* Catchall handler for the remaining syntax
*
* @param string $name Function name that was called
* @param array $params Original parameters
* @return bool If parsing should be continue
*/
public function __call($name, $params) {
if(count($params) == 3) {
$this->calls .= $params[0];
return true;
} else {
trigger_error('Error, handler function ' . hsc($name) . ' with ' . count($params) . ' parameters called which isn\'t implemented', E_USER_ERROR);
return false;
}
}
public function _finalize() {
// remove padding that is added by the parser in parse()
$this->calls = substr($this->calls, 1, -1);
}
}
+323
View File
@@ -0,0 +1,323 @@
<?php
/**
* Move Plugin Operation Execution
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
* @author Gary Owen <gary@isection.co.uk>
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
class helper_plugin_move_op extends DokuWiki_Plugin {
/**
* @var string symbol to make move operations easily recognizable in change log
*/
public $symbol = '↷';
/**
* @var array stores the affected pages of the last operation
*/
protected $affectedPages = array();
/**
* Check if the given page can be moved to the given destination
*
* @param $src
* @param $dst
* @return bool
*/
public function checkPage($src, $dst) {
// Check we have rights to move this document
if(!page_exists($src)) {
msg(sprintf($this->getLang('notexist'), $src), -1);
return false;
}
if(auth_quickaclcheck($src) < AUTH_EDIT) {
msg(sprintf($this->getLang('norights'), $src), -1);
return false;
}
// Check file is not locked
// checklock checks if the page lock hasn't expired and the page hasn't been locked by another user
// the file exists check checks if the page is reported unlocked if a lock exists which means that
// the page is locked by the current user
if(checklock($src) !== false || @file_exists(wikiLockFN($src))) {
msg(sprintf($this->getLang('filelocked'), $src), -1);
return false;
}
// Has the document name and/or namespace changed?
if($src == $dst) {
msg(sprintf($this->getLang('notchanged'), $src), -1);
return false;
}
// Check the page does not already exist
if(page_exists($dst)) {
msg(sprintf($this->getLang('exists'), $src, $dst), -1);
return false;
}
// Check if the current user can create the new page
if(auth_quickaclcheck($dst) < AUTH_CREATE) {
msg(sprintf($this->getLang('notargetperms'), $dst), -1);
return false;
}
return true;
}
/**
* Check if the given media file can be moved to the given destination
*
* @param $src
* @param $dst
* @return bool
*/
public function checkMedia($src, $dst) {
// Check we have rights to move this document
if(!file_exists(mediaFN($src))) {
msg(sprintf($this->getLang('medianotexist'), $src), -1);
return false;
}
if(auth_quickaclcheck($src) < AUTH_DELETE) {
msg(sprintf($this->getLang('nomediarights'), $src), -1);
return false;
}
// Has the document name and/or namespace changed?
if($src == $dst) {
msg(sprintf($this->getLang('medianotchanged'), $src), -1);
return false;
}
// Check the page does not already exist
if(@file_exists(mediaFN($dst))) {
msg(sprintf($this->getLang('mediaexists'), $src, $dst), -1);
return false;
}
// Check if the current user can create the new page
if(auth_quickaclcheck($dst) < AUTH_UPLOAD) {
msg(sprintf($this->getLang('nomediatargetperms'), $dst), -1);
return false;
}
// check if the file extension is unchanged
if (pathinfo(mediaFN($src), PATHINFO_EXTENSION) !== pathinfo(mediaFN($dst), PATHINFO_EXTENSION)) {
msg($this->getLang('extensionchange'), -1);
return false;
}
return true;
}
/**
* Execute a page move/rename
*
* @param string $src original ID
* @param string $dst new ID
* @return bool
*/
public function movePage($src, $dst) {
if(!$this->checkPage($src, $dst)) return false;
// lock rewrites
helper_plugin_move_rewrite::addLock();
/** @var helper_plugin_move_rewrite $Rewriter */
$Rewriter = plugin_load('helper', 'move_rewrite');
// remember what this page was called before the move in meta data
$Rewriter->setSelfMoveMeta($src);
// ft_backlinks() is not used here, as it does a hidden page and acl check but we really need all pages
$affected_pages = idx_get_indexer()->lookupKey('relation_references', $src);
$affected_pages[] = $dst; // the current page is always affected, because all relative links may have changed
$affected_pages = array_unique($affected_pages);
$src_ns = getNS($src);
$src_name = noNS($src);
$dst_ns = getNS($dst);
$dst_name = noNS($dst);
// pass this info on to other plugins
$eventdata = array(
// this is for compatibility to old plugin
'opts' => array(
'ns' => $src_ns,
'name' => $src_name,
'newns' => $dst_ns,
'newname' => $dst_name,
),
'affected_pages' => &$affected_pages,
'src_id' => $src,
'dst_id' => $dst,
);
// give plugins the option to add their own meta files to the list of files that need to be moved
// to the oldfiles/newfiles array or to adjust their own metadata, database, ...
// and to add other pages to the affected pages
$event = new Doku_Event('PLUGIN_MOVE_PAGE_RENAME', $eventdata);
if($event->advise_before()) {
lock($src);
/** @var helper_plugin_move_file $FileMover */
$FileMover = plugin_load('helper', 'move_file');
// Move the Subscriptions & Indexes (new feature since Spring 2013 release)
$Indexer = idx_get_indexer();
if(($idx_msg = $Indexer->renamePage($src, $dst)) !== true
|| ($idx_msg = $Indexer->renameMetaValue('relation_references', $src, $dst)) !== true
) {
msg(sprintf($this->getLang('indexerror'), $idx_msg), -1);
return false;
}
if(!$FileMover->movePageMeta($src_ns, $src_name, $dst_ns, $dst_name)) {
msg(sprintf($this->getLang('metamoveerror'), $src), -1);
return false;
}
// prepare the summary for the changelog entry
if($src_ns == $dst_ns) {
$lang_key = 'renamed';
} elseif($src_name == $dst_name) {
$lang_key = 'moved';
} else {
$lang_key = 'move_rename';
}
$summary = $this->symbol . ' ' . sprintf($this->getLang($lang_key), $src, $dst);
// Wait a second when the page has just been rewritten
$oldRev = filemtime(wikiFN($src));
if($oldRev == time()) sleep(1);
// Save the updated document in its new location
$text = rawWiki($src);
saveWikiText($dst, $text, $summary);
// Delete the orginal file
if(@file_exists(wikiFN($dst))) {
saveWikiText($src, '', $summary);
}
// Move the old revisions
if(!$FileMover->movePageAttic($src_ns, $src_name, $dst_ns, $dst_name)) {
// it's too late to stop the move, so just display a message.
msg(sprintf($this->getLang('atticmoveerror'), $src ), -1);
}
// Add meta data to all affected pages, so links get updated later
foreach($affected_pages as $id) {
$Rewriter->setMoveMeta($id, $src, $dst, 'pages');
}
unlock($src);
}
$event->advise_after();
// store this for later use
$this->affectedPages = $affected_pages;
// unlock rewrites
helper_plugin_move_rewrite::removeLock();
return true;
}
/**
* Execute a media file move/rename
*
* @param string $src original ID
* @param string $dst new ID
* @return bool true if the move was successfully executed
*/
public function moveMedia($src, $dst) {
if(!$this->checkMedia($src, $dst)) return false;
// get all pages using this media
$affected_pages = idx_get_indexer()->lookupKey('relation_media', $src);
$src_ns = getNS($src);
$src_name = noNS($src);
$dst_ns = getNS($dst);
$dst_name = noNS($dst);
// pass this info on to other plugins
$eventdata = array(
// this is for compatibility to old plugin
'opts' => array(
'ns' => $src_ns,
'name' => $src_name,
'newns' => $dst_ns,
'newname' => $dst_name,
),
'affected_pages' => &$affected_pages,
'src_id' => $src,
'dst_id' => $dst,
);
// give plugins the option to add their own meta files to the list of files that need to be moved
// to the oldfiles/newfiles array or to adjust their own metadata, database, ...
// and to add other pages to the affected pages
$event = new Doku_Event('PLUGIN_MOVE_MEDIA_RENAME', $eventdata);
if($event->advise_before()) {
/** @var helper_plugin_move_file $FileMover */
$FileMover = plugin_load('helper', 'move_file');
/** @var helper_plugin_move_rewrite $Rewriter */
$Rewriter = plugin_load('helper', 'move_rewrite');
// Move the Subscriptions & Indexes (new feature since Spring 2013 release)
$Indexer = idx_get_indexer();
if(($idx_msg = $Indexer->renameMetaValue('relation_media', $src, $dst)) !== true) {
msg(sprintf($this->getLang('indexerror'), $idx_msg), -1);
return false;
}
if(!$FileMover->moveMediaMeta($src_ns, $src_name, $dst_ns, $dst_name)) {
msg(sprintf($this->getLang('mediametamoveerror'), $src), -1);
return false;
}
// prepare directory
io_createNamespace($dst, 'media');
// move it FIXME this does not create a changelog entry!
if(!io_rename(mediaFN($src), mediaFN($dst))) {
msg(sprintf($this->getLang('mediamoveerror'), $src), -1);
return false;
}
// clean up old ns
io_sweepNS($src, 'mediadir');
// Move the old revisions
if(!$FileMover->moveMediaAttic($src_ns, $src_name, $dst_ns, $dst_name)) {
// it's too late to stop the move, so just display a message.
msg(sprintf($this->getLang('mediaatticmoveerror'), $src), -1);
}
// Add meta data to all affected pages, so links get updated later
foreach($affected_pages as $id) {
$Rewriter->setMoveMeta($id, $src, $dst, 'media');
}
}
$event->advise_after();
// store this for later use
$this->affectedPages = $affected_pages;
return true;
}
/**
* Get a list of pages that where affected by the last successful move operation
*
* @return array
*/
public function getAffectedPages() {
return $this->affectedPages;
}
}
+953
View File
@@ -0,0 +1,953 @@
<?php
/**
* Move Plugin Operation Planner
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
/**
* Class helper_plugin_move_plan
*
* This thing prepares and keeps progress info on complex move operations (eg. where more than a single
* object is affected).
*
* Please note: this has not a complex move resolver. Move operations may not depend on each other (eg. you
* can not use a namespace as source that will only be created by a different move operation) instead all given
* operations should be operations on the current state to come to a wanted future state. The tree manager takes
* care of that by abstracting all moves on a DOM representation first, then submitting the needed changes (eg.
* differences between now and wanted).
*
* Glossary:
*
* document - refers to either a page or a media file here
*/
class helper_plugin_move_plan extends DokuWiki_Plugin {
/** Number of operations per step */
const OPS_PER_RUN = 10;
const TYPE_PAGES = 1;
const TYPE_MEDIA = 2;
const CLASS_NS = 4;
const CLASS_DOC = 8;
/**
* @var array the options for this move plan
*/
protected $options = array(); // defaults are set in loadOptions()
/**
* @var array holds the location of the different list and state files
*/
protected $files = array();
/**
* @var array the planned moves
*/
protected $plan = array();
/**
* @var array temporary holder of document lists
*/
protected $tmpstore = array(
'pages' => array(),
'media' => array(),
'ns' => array(),
'affpg' => array(),
'miss' => array(),
'miss_media' => array(),
);
/** @var helper_plugin_move_op $MoveOperator */
protected $MoveOperator = null;
/**
* Constructor
*
* initializes state (if any) for continuiation of a running move op
*/
public function __construct() {
global $conf;
// set the file locations
$this->files = array(
'opts' => $conf['metadir'] . '/__move_opts',
'pagelist' => $conf['metadir'] . '/__move_pagelist',
'medialist' => $conf['metadir'] . '/__move_medialist',
'affected' => $conf['metadir'] . '/__move_affected',
'namespaces' => $conf['metadir'] . '/__move_namespaces',
'missing' => $conf['metadir'] . '/__move_missing',
'missing_media' => $conf['metadir'] . '/__move_missing_media',
);
$this->MoveOperator = plugin_load('helper', 'move_op');
$this->loadOptions();
}
/**
* Load the current options if any
*
* If no options are found, the default options will be extended by any available
* config options
*/
protected function loadOptions() {
// (re)set defaults
$this->options = array(
// status
'committed' => false,
'started' => 0,
// counters
'pages_all' => 0,
'pages_run' => 0,
'media_all' => 0,
'media_run' => 0,
'affpg_all' => 0,
'affpg_run' => 0,
// options
'autoskip' => $this->getConf('autoskip'),
'autorewrite' => $this->getConf('autorewrite'),
// errors
'lasterror' => false
);
// merge whatever options are saved currently
$file = $this->files['opts'];
if(file_exists($file)) {
$options = unserialize(io_readFile($file, false));
$this->options = array_merge($this->options, $options);
}
}
/**
* Save the current options
*
* @return bool
*/
protected function saveOptions() {
return io_saveFile($this->files['opts'], serialize($this->options));
}
/**
* Return the current state of an option, null for unknown options
*
* @param $name
* @return mixed|null
*/
public function getOption($name) {
if(isset($this->options[$name])) {
return $this->options[$name];
}
return null;
}
/**
* Set an option
*
* Note, this otpion will only be set to the current instance of this helper object. It will only
* be written to the option file once the plan gets committed
*
* @param $name
* @param $value
*/
public function setOption($name, $value) {
$this->options[$name] = $value;
}
/**
* Returns the progress of this plan in percent
*
* @return float
*/
public function getProgress() {
$max =
$this->options['pages_all'] +
$this->options['media_all'];
$remain =
$this->options['pages_run'] +
$this->options['media_run'];
if($this->options['autorewrite']) {
$max += $this->options['affpg_all'];
$remain += $this->options['affpg_run'];
}
if($max == 0) return 0;
return round((($max - $remain) * 100) / $max, 2);
}
/**
* Check if there is a move in progress currently
*
* @return bool
*/
public function inProgress() {
return (bool) $this->options['started'];
}
/**
* Check if this plan has been committed, yet
*
* @return bool
*/
public function isCommited() {
return $this->options['committed'];
}
/**
* Add a single page to be moved to the plan
*
* @param string $src
* @param string $dst
*/
public function addPageMove($src, $dst) {
$this->addMove($src, $dst, self::CLASS_DOC, self::TYPE_PAGES);
}
/**
* Add a single media file to be moved to the plan
*
* @param string $src
* @param string $dst
*/
public function addMediaMove($src, $dst) {
$this->addMove($src, $dst, self::CLASS_DOC, self::TYPE_MEDIA);
}
/**
* Add a page namespace to be moved to the plan
*
* @param string $src
* @param string $dst
*/
public function addPageNamespaceMove($src, $dst) {
$this->addMove($src, $dst, self::CLASS_NS, self::TYPE_PAGES);
}
/**
* Add a media namespace to be moved to the plan
*
* @param string $src
* @param string $dst
*/
public function addMediaNamespaceMove($src, $dst) {
$this->addMove($src, $dst, self::CLASS_NS, self::TYPE_MEDIA);
}
/**
* Plans the move of a namespace or document
*
* @param string $src ID of the item to move
* @param string $dst new ID of item namespace
* @param int $class (self::CLASS_NS|self::CLASS_DOC)
* @param int $type (PLUGIN_MOVE_TYPE_PAGE|self::TYPE_MEDIA)
* @throws Exception
*/
protected function addMove($src, $dst, $class = self::CLASS_NS, $type = self::TYPE_PAGES) {
if($this->options['committed']) throw new Exception('plan is committed already, can not be added to');
$src = cleanID($src);
$dst = cleanID($dst);
$this->plan[] = array(
'src' => $src,
'dst' => $dst,
'class' => $class,
'type' => $type
);
}
/**
* Abort any move or plan in progress and reset the helper
*/
public function abort() {
foreach($this->files as $file) {
@unlink($file);
}
$this->plan = array();
$this->loadOptions();
helper_plugin_move_rewrite::removeAllLocks();
}
/**
* This locks up the plan and prepares execution
*
* the plan is reordered an the needed move operations are gathered and stored in the appropriate
* list files
*
* @throws Exception if you try to commit a plan twice
* @return bool true if the plan was committed
*/
public function commit() {
global $conf;
if($this->options['committed']) throw new Exception('plan is committed already, can not be committed again');
helper_plugin_move_rewrite::addLock();
usort($this->plan, array($this, 'planSorter'));
// get all the documents to be moved and store them in their lists
foreach($this->plan as $move) {
if($move['class'] == self::CLASS_DOC) {
// these can just be added
$this->addToDocumentList($move['src'], $move['dst'], $move['type']);
} else {
// here we need a list of content first, search for it
$docs = array();
$path = utf8_encodeFN(str_replace(':', '/', $move['src']));
$opts = array('depth' => 0, 'skipacl' => true);
if($move['type'] == self::TYPE_PAGES) {
search($docs, $conf['datadir'], 'search_allpages', $opts, $path);
} else {
search($docs, $conf['mediadir'], 'search_media', $opts, $path);
}
// how much namespace to strip?
if($move['src'] !== '') {
$strip = strlen($move['src']) + 1;
} else {
$strip = 0;
}
if($move['dst']) $move['dst'] .= ':';
// now add all the found documents to our lists
foreach($docs as $doc) {
$from = $doc['id'];
$to = $move['dst'] . substr($doc['id'], $strip);
$this->addToDocumentList($from, $to, $move['type']);
}
// remember the namespace move itself
if($move['type'] == self::TYPE_PAGES) {
// FIXME we use this to move namespace subscriptions later on and for now only do it on
// page namespace moves, but subscriptions work for both, but what when only one of
// them is moved? Should it be copied then? Complicated. This is good enough for now
$this->addToDocumentList($move['src'], $move['dst'], self::CLASS_NS);
}
$this->findMissingDocuments($move['src'] . ':', $move['dst'],$move['type']);
}
// store what pages are affected by this move
$this->findAffectedPages($move['src'], $move['dst'], $move['class'], $move['type']);
}
$this->storeDocumentLists();
if(!$this->options['pages_all'] && !$this->options['media_all']) {
msg($this->getLang('noaction'), -1);
return false;
}
$this->options['committed'] = true;
$this->saveOptions();
return true;
}
/**
* Execute the next steps
*
* @param bool $skip set to true to skip the next first step (skip error)
* @return bool|int false on errors, otherwise the number of remaining steps
* @throws Exception
*/
public function nextStep($skip = false) {
if(!$this->options['committed']) throw new Exception('plan is not committed yet!');
// execution has started
if(!$this->options['started']) $this->options['started'] = time();
helper_plugin_move_rewrite::addLock();
if(@filesize($this->files['pagelist']) > 1) {
$todo = $this->stepThroughDocuments(self::TYPE_PAGES, $skip);
if($todo === false) return $this->storeError();
return max($todo, 1); // force one more call
}
if(@filesize($this->files['medialist']) > 1) {
$todo = $this->stepThroughDocuments(self::TYPE_MEDIA, $skip);
if($todo === false) return $this->storeError();
return max($todo, 1); // force one more call
}
if(@filesize($this->files['missing']) > 1 && @filesize($this->files['affected']) > 1) {
$todo = $this->stepThroughMissingDocuments(self::TYPE_PAGES);
if($todo === false) return $this->storeError();
return max($todo, 1); // force one more call
}
if(@filesize($this->files['missing_media']) > 1 && @filesize($this->files['affected']) > 1) {
$todo = $this->stepThroughMissingDocuments(self::TYPE_MEDIA);
if($todo === false)return $this->storeError();
return max($todo, 1); // force one more call
}
if(@filesize($this->files['namespaces']) > 1) {
$todo = $this->stepThroughNamespaces();
if($todo === false) return $this->storeError();
return max($todo, 1); // force one more call
}
helper_plugin_move_rewrite::removeAllLocks();
if($this->options['autorewrite'] && @filesize($this->files['affected']) > 1) {
$todo = $this->stepThroughAffectedPages();
if($todo === false) return $this->storeError();
return max($todo, 1); // force one more call
}
// we're done here, clean up
$this->abort();
return 0;
}
/**
* Returns the list of page and media moves and the affected pages as a HTML list
*
* @return string
*/
public function previewHTML() {
$html = '';
$html .= '<ul>';
if(@file_exists($this->files['pagelist'])) {
$pagelist = file($this->files['pagelist']);
foreach($pagelist as $line) {
list($old, $new) = explode("\t", trim($line));
$html .= '<li class="page"><div class="li">';
$html .= hsc($old);
$html .= '→';
$html .= hsc($new);
$html .= '</div></li>';
}
}
if(@file_exists($this->files['medialist'])) {
$medialist = file($this->files['medialist']);
foreach($medialist as $line) {
list($old, $new) = explode("\t", trim($line));
$html .= '<li class="media"><div class="li">';
$html .= hsc($old);
$html .= '→';
$html .= hsc($new);
$html .= '</div></li>';
}
}
if(@file_exists($this->files['affected'])) {
$medialist = file($this->files['affected']);
foreach($medialist as $page) {
$html .= '<li class="affected"><div class="li">';
$html .= '↷';
$html .= hsc($page);
$html .= '</div></li>';
}
}
$html .= '</ul>';
return $html;
}
/**
* Step through the next bunch of pages or media files
*
* @param int $type (self::TYPE_PAGES|self::TYPE_MEDIA)
* @param bool $skip should the first item be skipped?
* @return bool|int false on error, otherwise the number of remaining documents
*/
protected function stepThroughDocuments($type = self::TYPE_PAGES, $skip = false) {
if($type == self::TYPE_PAGES) {
$file = $this->files['pagelist'];
$mark = 'P';
$call = 'movePage';
$items_run_counter = 'pages_run';
} else {
$file = $this->files['medialist'];
$mark = 'M';
$call = 'moveMedia';
$items_run_counter = 'media_run';
}
$doclist = fopen($file, 'a+');
for($i = 0; $i < helper_plugin_move_plan::OPS_PER_RUN; $i++) {
$log = "";
$line = $this->getLastLine($doclist);
if($line === false) {
break;
}
list($src, $dst) = explode("\t", trim($line));
// should this item be skipped?
if($skip === true) {
$skip = false;
} else {
// move the page
if(!$this->MoveOperator->$call($src, $dst)) {
$log .= $this->build_log_line($mark, $src, $dst, false); // FAILURE!
// automatically skip this item only if wanted...
if(!$this->options['autoskip']) {
// ...otherwise abort the operation
fclose($doclist);
$return_items_run = false;
break;
}
} else {
$log .= $this->build_log_line($mark, $src, $dst, true); // SUCCESS!
}
}
/*
* This adjusts counters and truncates the document list correctly
* It is used to finalize a successful or skipped move
*/
ftruncate($doclist, ftell($doclist));
$this->options[$items_run_counter]--;
$return_items_run = $this->options[$items_run_counter];
$this->write_log($log);
$this->saveOptions();
}
if ($return_items_run !== false) {
fclose($doclist);
}
return $return_items_run;
}
/**
* Step through the next bunch of pages that need link corrections
*
* @return bool|int false on error, otherwise the number of remaining documents
*/
protected function stepThroughAffectedPages() {
/** @var helper_plugin_move_rewrite $Rewriter */
$Rewriter = plugin_load('helper', 'move_rewrite');
// handle affected pages
$doclist = fopen($this->files['affected'], 'a+');
for($i = 0; $i < helper_plugin_move_plan::OPS_PER_RUN; $i++) {
$page = $this->getLastLine($doclist);
if($page === false) break;
// rewrite it
$Rewriter->rewritePage($page);
// update the list file
ftruncate($doclist, ftell($doclist));
$this->options['affpg_run']--;
$this->saveOptions();
}
fclose($doclist);
return $this->options['affpg_run'];
}
/**
* Step through all the links to missing pages that should be moved
*
* This simply adds the moved missing pages to all affected pages meta data. This will add
* the meta data to pages not linking to the affected pages but this should still be faster
* than figuring out which pages need this info.
*
* This does not step currently, but handles all pages in one step.
*
* @param int $type
*
* @return int always 0
* @throws Exception
*/
protected function stepThroughMissingDocuments($type = self::TYPE_PAGES) {
if($type != self::TYPE_PAGES && $type != self::TYPE_MEDIA) {
throw new Exception('wrong type specified');
}
/** @var helper_plugin_move_rewrite $Rewriter */
$Rewriter = plugin_load('helper', 'move_rewrite');
$miss = array();
if ($type == self::TYPE_PAGES) {
$missing_fn = $this->files['missing'];
} else {
$missing_fn = $this->files['missing_media'];
}
$missing = file($missing_fn);
foreach($missing as $line) {
$line = trim($line);
if($line == '') continue;
list($src, $dst) = explode("\t", $line);
$miss[$src] = $dst;
}
$affected = file($this->files['affected']);
foreach($affected as $page){
$page = trim($page);
if ($type == self::TYPE_PAGES) {
$Rewriter->setMoveMetas($page, $miss, 'pages');
} else {
$Rewriter->setMoveMetas($page, $miss, 'media');
}
}
unlink($missing_fn);
return 0;
}
/**
* Step through all the namespace moves
*
* This does not step currently, but handles all namespaces in one step.
*
* Currently moves namespace subscriptions only.
*
* @return int always 0
* @todo maybe add an event so plugins can move more stuff?
* @todo fixed that $src and $dst are seperated by tab, not newline. This method has no tests?
*/
protected function stepThroughNamespaces() {
/** @var helper_plugin_move_file $FileMover */
$FileMover = plugin_load('helper', 'move_file');
$lines = io_readFile($this->files['namespaces']);
$lines = explode("\n", $lines);
foreach($lines as $line) {
// There is an empty line at the end of the list.
if ($line === '') continue;
list($src, $dst) = explode("\t", trim($line));
$FileMover->moveNamespaceSubscription($src, $dst);
}
@unlink($this->files['namespaces']);
return 0;
}
/**
* Retrieve the last error from the MSG array and store it in the options
*
* @todo rebuild error handling based on exceptions
*
* @return bool always false
*/
protected function storeError() {
global $MSG;
if(is_array($MSG) && count($MSG)) {
$last = array_shift($MSG);
$this->options['lasterror'] = $last['msg'];
unset($GLOBALS['MSG']);
} else {
$this->options['lasterror'] = 'Unknown error';
}
$this->saveOptions();
return false;
}
/**
* Reset the error state
*/
protected function clearError() {
$this->options['lasterror'] = false;
$this->saveOptions();
}
/**
* Get the last error message or false if no error occured
*
* @return bool|string
*/
public function getLastError() {
return $this->options['lasterror'];
}
/**
* Appends a page move operation in the list file
*
* If the src has been added before, this is ignored. This makes sure you can move a single page
* out of a namespace first, then move the namespace somewhere else.
*
* @param string $src
* @param string $dst
* @param int $type
* @throws Exception
*/
protected function addToDocumentList($src, $dst, $type = self::TYPE_PAGES) {
if($type == self::TYPE_PAGES) {
$store = 'pages';
} else if($type == self::TYPE_MEDIA) {
$store = 'media';
} else if($type == self::CLASS_NS) {
$store = 'ns';
} else {
throw new Exception('Unknown type ' . $type);
}
if(!isset($this->tmpstore[$store][$src])) {
$this->tmpstore[$store][$src] = $dst;
}
}
/**
* Add the list of pages to the list of affected pages whose links need adjustment
*
* @param string|array $pages
*/
protected function addToAffectedPagesList($pages) {
if(!is_array($pages)) $pages = array($pages);
foreach($pages as $page) {
if(!isset($this->tmpstore['affpg'][$page])) {
$this->tmpstore['affpg'][$page] = true;
}
}
}
/**
* Looks up pages that will be affected by a move of $src
*
* Calls addToAffectedPagesList() directly to store the result
*
* @param string $src source namespace
* @param string $dst destination namespace
* @param int $class
* @param int $type
*/
protected function findAffectedPages($src, $dst, $class, $type) {
$idx = idx_get_indexer();
if($class == self::CLASS_NS) {
$src_ = "$src:*"; // use wildcard lookup for namespaces
} else {
$src_ = $src;
}
$pages = array();
if($type == self::TYPE_PAGES) {
$pages = $idx->lookupKey('relation_references', $src_);
$len = strlen($src);
foreach($pages as &$page) {
if (substr($page, 0, $len + 1) === "$src:") {
$page = $dst . substr($page, $len + 1);
}
}
unset($page);
} else if($type == self::TYPE_MEDIA) {
$pages = $idx->lookupKey('relation_media', $src_);
}
$this->addToAffectedPagesList($pages);
}
/**
* Find missing pages in the $src namespace
*
* @param string $src source namespace
* @param string $dst destination namespace
* @param int $type either self::TYPE_PAGES or self::TYPE_MEDIA
*/
protected function findMissingDocuments($src, $dst, $type = self::TYPE_PAGES) {
global $conf;
// FIXME this duplicates Doku_Indexer::getIndex()
if ($type == self::TYPE_PAGES) {
$fn = $conf['indexdir'] . '/relation_references_w.idx';
} else {
$fn = $conf['indexdir'] . '/relation_media_w.idx';
}
if (!@file_exists($fn)){
$referenceidx = array();
} else {
$referenceidx = file($fn, FILE_IGNORE_NEW_LINES);
}
$len = strlen($src);
foreach($referenceidx as $idx => $page) {
if(substr($page, 0, $len) != "$src") continue;
// remember missing pages
if ($type == self::TYPE_PAGES) {
if(!page_exists($page)) {
$newpage = $dst . substr($page, $len);
$this->tmpstore['miss'][$page] = $newpage;
}
} else {
if(!file_exists(mediaFN($page))){
$newpage = $dst . substr($page, $len);
$this->tmpstore['miss_media'][$page] = $newpage;
}
}
}
}
/**
* Store the aggregated document lists in the file system and reset the internal storage
*
* @throws Exception
*/
protected function storeDocumentLists() {
$lists = array(
'pages' => $this->files['pagelist'],
'media' => $this->files['medialist'],
'ns' => $this->files['namespaces'],
'affpg' => $this->files['affected'],
'miss' => $this->files['missing'],
'miss_media' => $this->files['missing_media'],
);
foreach($lists as $store => $file) {
// anything to do?
$count = count($this->tmpstore[$store]);
if(!$count) continue;
// prepare and save content
$data = '';
$this->tmpstore[$store] = array_reverse($this->tmpstore[$store]); // store in reverse order
foreach($this->tmpstore[$store] as $src => $dst) {
if($dst === true) {
$data .= "$src\n"; // for affected pages only one ID is saved
} else {
$data .= "$src\t$dst\n";
}
}
io_saveFile($file, $data);
// set counters
if($store != 'ns') {
$this->options[$store . '_all'] = $count;
$this->options[$store . '_run'] = $count;
}
// reset the list
$this->tmpstore[$store] = array();
}
}
/**
* Get the last line from the list that is stored in the file that is referenced by the handle
* The handle is set to the newline before the file id
*
* @param resource $handle The file handle to read from
* @return string|bool the last id from the list or false if there is none
*/
protected function getLastLine($handle) {
// begin the seek at the end of the file
fseek($handle, 0, SEEK_END);
$line = '';
// seek one backwards as long as it's possible
while(fseek($handle, -1, SEEK_CUR) >= 0) {
$c = fgetc($handle);
if($c === false) return false; // EOF, i.e. the file is empty
fseek($handle, -1, SEEK_CUR); // reset the position to the character that was read
if($c == "\n") {
if($line === '') {
continue; // this line was empty, continue
} else {
break; // we have a line, finish
}
}
$line = $c . $line; // prepend char to line
}
if($line === '') return false; // beginning of file reached and no content
return $line;
}
/**
* Callback for usort to sort the move plan
*
* @param $a
* @param $b
* @return int
*/
public function planSorter($a, $b) {
// do page moves before namespace moves
if($a['class'] == self::CLASS_DOC && $b['class'] == self::CLASS_NS) {
return -1;
}
if($a['class'] == self::CLASS_NS && $b['class'] == self::CLASS_DOC) {
return 1;
}
// do pages before media
if($a['type'] == self::TYPE_PAGES && $b['type'] == self::TYPE_MEDIA) {
return -1;
}
if($a['type'] == self::TYPE_MEDIA && $b['type'] == self::TYPE_PAGES) {
return 1;
}
// from here on we compare only apples to apples
// we sort by depth of namespace, deepest namespaces first
$alen = substr_count($a['src'], ':');
$blen = substr_count($b['src'], ':');
if($alen > $blen) {
return -1;
} elseif($alen < $blen) {
return 1;
}
return 0;
}
/**
* Create line to log result of an operation
*
* @param string $type
* @param string $from
* @param string $to
* @param bool $success
*
* @return string
*
* @author Andreas Gohr <gohr@cosmocode.de>
* @author Michael Große <grosse@cosmocode.de>
*/
public function build_log_line ($type, $from, $to, $success) {
global $MSG;
$now = time();
$date = date('Y-m-d H:i:s', $now); // for human readability
if($success) {
$ok = 'success';
$msg = '';
} else {
$ok = 'failed';
$msg = $MSG[count($MSG) - 1]['msg']; // get detail from message array
}
$log = "$now\t$date\t$type\t$from\t$to\t$ok\t$msg\n";
return $log;
}
/**
* write log to file
*
* @param $log
*/
protected function write_log ($log) {
global $conf;
$optime = $this->options['started'];
$file = $conf['cachedir'] . '/move/' . strftime('%Y%m%d-%H%M%S', $optime) . '.log';
io_saveFile($file, $log, true);
}
}
+297
View File
@@ -0,0 +1,297 @@
<?php
/**
* Move Plugin Page Rewriter
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Michael Hamann <michael@content-space.de>
* @author Gary Owen <gary@isection.co.uk>
* @author Andreas Gohr <gohr@cosmocode.de>
*/
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
// load required handler class
require_once(dirname(__FILE__) . '/handler.php');
/**
* Class helper_plugin_move_rewrite
*
* This class handles the rewriting of wiki text to update the links
*/
class helper_plugin_move_rewrite extends DokuWiki_Plugin {
/**
* Under what key is move data to be saved in metadata
*/
const METAKEY = 'plugin_move';
/**
* What is they filename of the lockfile
*/
const LOCKFILENAME = '_plugin_move.lock';
/**
* @var string symbol to make move operations easily recognizable in change log
*/
public $symbol = '↷';
/**
* This function loads and returns the persistent metadata for the move plugin. If there is metadata for the
* pagemove plugin (not the old one but the version that immediately preceeded the move plugin) it will be migrated.
*
* @param string $id The id of the page the metadata shall be loaded for
* @return array|null The metadata of the page
*/
public function getMoveMeta($id) {
$all_meta = p_get_metadata($id, '', METADATA_DONT_RENDER);
/* todo migrate old move data
if(isset($all_meta['plugin_pagemove']) && !is_null($all_meta['plugin_pagemove'])) {
if(isset($all_meta[self::METAKEY])) {
$all_meta[self::METAKEY] = array_merge_recursive($all_meta['plugin_pagemove'], $all_meta[self::METAKEY]);
} else {
$all_meta[self::METAKEY] = $all_meta['plugin_pagemove'];
}
p_set_metadata($id, array(self::METAKEY => $all_meta[self::METAKEY], 'plugin_pagemove' => null), false, true);
}
*/
// discard missing or empty array or string
$meta = !empty($all_meta[self::METAKEY]) ? $all_meta[self::METAKEY] : array();
if(!isset($meta['origin'])) {
$meta['origin'] = '';
}
if(!isset($meta['pages'])) {
$meta['pages'] = array();
}
if(!isset($meta['media'])) {
$meta['media'] = array();
}
return $meta;
}
/**
* Remove any existing move meta data for the given page
*
* @param $id
*/
public function unsetMoveMeta($id) {
p_set_metadata($id, array(self::METAKEY => array()), false, true);
}
/**
* Add info about a moved document to the metadata of an affected page
*
* @param string $id affected page
* @param string $src moved document's original id
* @param string $dst moved document's new id
* @param string $type 'media' or 'page'
* @throws Exception on wrong argument
*/
public function setMoveMeta($id, $src, $dst, $type) {
$this->setMoveMetas($id, array($src => $dst), $type);
}
/**
* Add info about several moved documents to the metadata of an affected page
*
* @param string $id affected page
* @param array $moves list of moves (src is key, dst is value)
* @param string $type 'media' or 'page'
* @throws Exception
*/
public function setMoveMetas($id, $moves, $type) {
if($type != 'pages' && $type != 'media') {
throw new Exception('wrong type specified');
}
if(!page_exists($id, '', false)) {
return;
}
$meta = $this->getMoveMeta($id);
foreach($moves as $src => $dst) {
$meta[$type][] = array($src, $dst);
}
p_set_metadata($id, array(self::METAKEY => $meta), false, true);
}
/**
* Store info about the move of a page in its own meta data
*
* This has to be called before the move is executed
*
* @param string $id moved page's original (and still current) id
*/
public function setSelfMoveMeta($id) {
$meta = $this->getMoveMeta($id);
// was this page moved multiple times? keep the orignal name til rewriting occured
if(isset($meta['origin']) && $meta['origin'] !== '') {
return;
}
$meta['origin'] = $id;
p_set_metadata($id, array(self::METAKEY => $meta), false, true);
}
/**
* Check if rewrites may be executed within this process right now
*
* @return bool
*/
public static function isLocked() {
global $PLUGIN_MOVE_WORKING;
global $conf;
$lockfile = $conf['lockdir'] . self::LOCKFILENAME;
return ((isset($PLUGIN_MOVE_WORKING) && $PLUGIN_MOVE_WORKING > 0) || file_exists($lockfile));
}
/**
* Do not allow any rewrites in this process right now
*/
public static function addLock() {
global $PLUGIN_MOVE_WORKING;
global $conf;
$PLUGIN_MOVE_WORKING = $PLUGIN_MOVE_WORKING ? $PLUGIN_MOVE_WORKING + 1 : 1;
$lockfile = $conf['lockdir'] . self::LOCKFILENAME;
if (!file_exists($lockfile)) {
io_savefile($lockfile, "1\n");
} else {
$stack = intval(file_get_contents($lockfile));
++$stack;
io_savefile($lockfile, strval($stack));
}
}
/**
* Allow rerites in this process again, unless some other lock exists
*/
public static function removeLock() {
global $PLUGIN_MOVE_WORKING;
global $conf;
$PLUGIN_MOVE_WORKING = $PLUGIN_MOVE_WORKING ? $PLUGIN_MOVE_WORKING - 1 : 0;
$lockfile = $conf['lockdir'] . self::LOCKFILENAME;
if (!file_exists($lockfile)) {
throw new Exception("removeLock failed: lockfile missing");
} else {
$stack = intval(file_get_contents($lockfile));
if($stack === 1) {
unlink($lockfile);
} else {
--$stack;
io_savefile($lockfile, strval($stack));
}
}
}
/**
* Allow rewrites in this process again.
*
* @author Michael Große <grosse@cosmocode.de>
*/
public static function removeAllLocks() {
global $conf;
$lockfile = $conf['lockdir'] . self::LOCKFILENAME;
if (file_exists($lockfile)) {
unlink($lockfile);
}
unset($GLOBALS['PLUGIN_MOVE_WORKING']);
}
/**
* Rewrite a text in order to fix the content after the given moves.
*
* @param string $id The id of the wiki page, if the page itself was moved the old id
* @param string $text The text to be rewritten
* @return string The rewritten wiki text
*/
public function rewrite($id, $text) {
$meta = $this->getMoveMeta($id);
$handlers = array();
$pages = $meta['pages'];
$media = $meta['media'];
$origin = $meta['origin'];
if($origin == '') $origin = $id;
$data = array(
'id' => $id,
'origin' => &$origin,
'pages' => &$pages,
'media_moves' => &$media,
'handlers' => &$handlers
);
/*
* PLUGIN_MOVE_HANDLERS REGISTER event:
*
* Plugin handlers can be registered in the $handlers array, the key is the plugin name as it is given to the handler
* The handler needs to be a valid callback, it will get the following parameters:
* $match, $state, $pos, $pluginname, $handler. The first three parameters are equivalent to the parameters
* of the handle()-function of syntax plugins, the $pluginname is just the plugin name again so handler functions
* that handle multiple plugins can distinguish for which the match is. The last parameter is the handler object
* which is an instance of helper_plugin_move_handle
*/
trigger_event('PLUGIN_MOVE_HANDLERS_REGISTER', $data);
$modes = p_get_parsermodes();
// Create the parser
$Parser = new Doku_Parser();
// Add the Handler
/** @var $Parser->Handler helper_plugin_move_handler */
$Parser->Handler = $this->loadHelper('move_handler');
$Parser->Handler->init($id, $origin, $pages, $media, $handlers);
//add modes to parser
foreach($modes as $mode) {
$Parser->addMode($mode['mode'], $mode['obj']);
}
return $Parser->parse($text);
}
/**
* Rewrite the text of a page according to the recorded moves, the rewritten text is saved
*
* @param string $id The id of the page that shall be rewritten
* @param string|null $text Old content of the page. When null is given the content is loaded from disk
* @return string|bool The rewritten content, false on error
*/
public function rewritePage($id, $text = null, $save = true) {
$meta = $this->getMoveMeta($id);
if(is_null($text)) {
$text = rawWiki($id);
}
if($meta['pages'] || $meta['media']) {
$old_text = $text;
$text = $this->rewrite($id, $text);
$changed = ($old_text != $text);
$file = wikiFN($id, '', false);
if ($save === true) {
if(is_writable($file) || !$changed) {
if($changed) {
// Wait a second when the page has just been rewritten
$oldRev = filemtime(wikiFN($id));
if($oldRev == time()) sleep(1);
saveWikiText($id, $text, $this->symbol . ' ' . $this->getLang('linkchange'), $this->getConf('minor'));
}
$this->unsetMoveMeta($id);
} else {
// FIXME: print error here or fail silently?
msg('Error: Page ' . hsc($id) . ' needs to be rewritten because of page renames but is not writable.', -1);
return false;
}
}
}
return $text;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M18,4V3A1,1 0 0,0 17,2H5A1,1 0 0,0 4,3V7A1,1 0 0,0 5,8H17A1,1 0 0,0 18,7V6H19V10H9V21A1,1 0 0,0 10,22H12A1,1 0 0,0 13,21V12H21V4H18Z" /></svg>

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

+10
View File
@@ -0,0 +1,10 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author aljailane <shop@souqye.com>
*/
$lang['menu'] = 'نقل الصفحات ومساحات الأسماء';
$lang['inprogress'] = '(التحرك معلق)';
$lang['treelink'] = 'بدلاً من هذا النموذج البسيط ، يمكنك إدارة إعادة الهيكلة المعقدة لموقع wiki الخاص بك باستخدام <a href="%s"> مدير النقل المستند إلى الشجرة </a>. ';
+67
View File
@@ -0,0 +1,67 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Robert Surý <rsurycz@seznam.cz>
* @author Tomáš Borland Valenta
* @author Pavel Kochman
*/
$lang['menu'] = 'Přesun/přejmenování stránky';
$lang['inprogress'] = '(probíhá přesun)';
$lang['treelink'] = 'Alternativou k tomuto jednoduchému formuláři můžete použít komplexní přeskupení vaší wiki pomocí <a href="%s">stromového manažeru přesunu</a>.';
$lang['notexist'] = 'Stránka \'%s\' neexistuje.';
$lang['norights'] = 'Nedostatečné oprávnění editovat \'%s\'.';
$lang['filelocked'] = 'Stránka \'%s\' je uzamčna - zkuste prosím znovu později.';
$lang['notchanged'] = 'Žádný cíl pro stránku \'%s\' (umístění nezměněno).';
$lang['exists'] = 'Stránku \'%s\' nelze přesunout do \'%s\', cíl již existuje.';
$lang['notargetperms'] = 'Nemáte oprávnění vytvořit stránku \'%s\'.';
$lang['medianotexist'] = 'Médium \'%s\' neexistuje.';
$lang['nomediarights'] = 'Nedostatečné oprávnění ke smazání \'%s\'.';
$lang['medianotchanged'] = 'Žádný cíl pro médium \'%s\' (umístění nezměněno).';
$lang['mediaexists'] = 'Médium \'%s\' nelze přesunout do \'%s\', cíl již existuje.';
$lang['nomediatargetperms'] = 'Nemáte oprávnění vytvořit médium \'%s\'.';
$lang['indexerror'] = 'Chyba při aktualizaci search index \'%s\'.';
$lang['metamoveerror'] = 'Meta soubory stránky \'%s\' nemohou být přesunut.';
$lang['atticmoveerror'] = 'Staré verze stránky \'%s\' nemohou být přesunuty. Prosím, přsuňte je ručně.';
$lang['mediametamoveerror'] = 'Meta soubory média \'%s\' nemohou být přesunuty.';
$lang['mediamoveerror'] = 'Přesunutí média \'%s\' selhalo.';
$lang['mediaatticmoveerror'] = 'Staré verze média \'%s\' nemohou být přesunuty. Prosím, přsuňte je ručně.';
$lang['renamed'] = 'Stránka přejmenována z \'%s\' na \'%s\'';
$lang['moved'] = 'Stránka přesunuta z \'%s\' do \'%s\'';
$lang['move_rename'] = 'Stránka přesunuta a přejmenována z \'%s\' do \'%s\'';
$lang['delete'] = 'Smazáno pluginem move';
$lang['linkchange'] = 'Odkaz upraven z důvodu přesunutí';
$lang['intro'] = 'Přesun dosud nebyl zahájen!';
$lang['preview'] = 'Náhled změn, které budou provedeny.';
$lang['inexecution'] = 'Předchozí přesun nebyl dokončen - použijte tlačítko dole k pokračování či přerušení přesunu.';
$lang['btn_start'] = 'Start';
$lang['btn_continue'] = 'Pokračovat';
$lang['btn_retry'] = 'Znovu';
$lang['btn_skip'] = 'Přeskočit položku';
$lang['btn_abort'] = 'Přerušit';
$lang['legend'] = 'Přesunout aktuální stránku nebo jmenný prostor';
$lang['movepage'] = 'Přesunout stránku';
$lang['movens'] = 'Přesunout aktuální jmenný prostor';
$lang['dst'] = 'Nové jméno:';
$lang['content_to_move'] = 'Obsah k přesunutí:';
$lang['autoskip'] = 'Ignorovat chyby a přeskočit stránky a média, které nemohou být přesunuty';
$lang['autorewrite'] = 'Přepsat odkazy po úspěšmén přesunu';
$lang['move_pages'] = 'Stránky';
$lang['move_media'] = 'Média';
$lang['move_media_and_pages'] = 'Stránky a média';
$lang['nodst'] = 'Žádné nové jméno';
$lang['noaction'] = 'Nebyl definován přesun';
$lang['renamepage'] = 'Přejmenovat stránku';
$lang['cantrename'] = 'Stránka nemůže být právě přejmenována. Zkuste to později.';
$lang['js']['rename'] = 'Přejmenovat';
$lang['js']['cancel'] = 'Zrušit';
$lang['js']['newname'] = 'Nový název stránky:';
$lang['js']['inprogress'] = 'Přesouvám stránky a upravuji odkazy...';
$lang['js']['complete'] = 'Přesun byl dokončen.';
$lang['js']['renameitem'] = 'Přejmenovat tuto položku';
$lang['js']['add'] = 'Vytvořit nový jmenný prostor';
$lang['js']['duplicate'] = 'Lituji, ale \'%s\' již existuje ve jmenném prosoru.';
$lang['root'] = '[Kořen]';
$lang['noscript'] = 'Tato vlastost vyžaduje JavaScript';
$lang['moveinprogress'] = 'Právě probíhá jiný přsun, proto nyní nemůžete použít tento nástroj.';
+10
View File
@@ -0,0 +1,10 @@
====== Move ======
Pomocí tohoto pluginu lze přesunout nebo přejmenovat aktuální stránku. Platí však jistá omezení:
* Musíte mít práva na danou stránku.
* Stránky které se přesouvají nesmí být zamčeny pro úpravu.
* Pro přesun stránky potřebujete práva pro zápis v cílovém místě.
* Nelze přesunout stránku někam, kde již existuje stránka stejného jména.
Všechny odkazy na a ze stránky budou upraveny podle nového umístění stránky.
+3
View File
@@ -0,0 +1,3 @@
====== Probíhá přesun... ======
Prosím nezavírejte tuto stránku, dokud přesun neskončí.
+13
View File
@@ -0,0 +1,13 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Robert Surý <rsurycz@seznam.cz>
* @author Pavel Kochman
*/
$lang['allowrename'] = 'Povolit přeijmenovat stránky témto skupinám a uživatelům (oddělených čárkou).';
$lang['minor'] = 'Označit úpravu odkaů jako drobná změna? Drobné změny nebudou viditelné v RSS feeds a v odebíraných mailech změn.';
$lang['autoskip'] = 'Zapnout automatické přeskakování chyb při přesouvání namespace.';
$lang['autorewrite'] = 'Zapnout automatické přepisování odkazů po přesunutí namespace.';
$lang['pagetools_integration'] = 'Přidat tlačítko pro přejmenování do nástrojů stránky';
+3
View File
@@ -0,0 +1,3 @@
====== Move Manager =====
Tento interface umožňuje přeorganizovat vaše wiki namespace, stránky a média pomocí Drag'n'Drop.
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Jacob Palm <jacobpalmdk@icloud.com>
*/
$lang['menu'] = 'Flyt sider og navnerum';
$lang['inprogress'] = '(flytning afventer)';
$lang['treelink'] = 'Som alternativ til denne simple formular, kan du omstrukturere din wiki ved hjælp af trævisningen i <a href="%s">flytningshåndtering</a>.';
$lang['notexist'] = 'Siden %s findes ikke';
$lang['norights'] = 'Du har ikke rettigheder til at redigere %s.';
$lang['filelocked'] = 'Siden %s er låst. Prøv igen senere.';
$lang['notchanged'] = 'Ingen ny lokation til siden %s angivet (lokation uændret).';
$lang['exists'] = 'Siden %s kan ikke flyttes til %s, da destinationssiden allerede findes.';
$lang['notargetperms'] = 'Du har ikke rettigheder til at oprette siden %s.';
$lang['medianotexist'] = 'Mediefilen %s findes ikke';
$lang['nomediarights'] = 'Du har ikke rettigheder til at slette %s.';
$lang['medianotchanged'] = 'Ingen ny lokation til siden %s angivet (lokation uændret).';
$lang['mediaexists'] = 'Mediet %s kan ikke flyttes til %s, der findes allerede et medie der.';
$lang['nomediatargetperms'] = 'Du har ikke rettigheder til at oprette mediefilen %s.';
$lang['indexerror'] = 'Fejl under opdatering af søgeindeks %s';
$lang['metamoveerror'] = 'Meta filerne til siden %s kunne ikke flyttes';
$lang['atticmoveerror'] = 'Attic-filerne til siden %s kunne ikke flyttes. Disse skal flyttes manuelt.';
$lang['mediametamoveerror'] = 'Meta filerne til mediefilen %s kunne ikke flyttes';
$lang['mediamoveerror'] = 'Flytning af mediefilen %s fejlede';
$lang['mediaatticmoveerror'] = 'Attic-filerne til mediefilen %s kunne ikke flyttes. Disse skal flyttes manuelt.';
$lang['renamed'] = 'Sidenavn ændret fra %s til %s';
$lang['moved'] = 'Side flyttet fra %s til %s';
$lang['move_rename'] = 'Side flyttet og omdøbt fra %s til %s';
$lang['delete'] = 'Slettet af flytningsudvidelse';
$lang['linkchange'] = 'Links tilrettede pga. en flytningsoperation';
$lang['intro'] = 'Flytningsoperation er ikke startet endnu!';
$lang['preview'] = 'Forhåndsvisning af ændringer der bliver udført.';
$lang['inexecution'] = 'En tidligere flytningsoperation blev ikke fuldført - brug knapperne herunder til at fortsætte eller afbryde flytningen.';
$lang['btn_start'] = 'Start';
$lang['btn_continue'] = 'Fortsæt';
$lang['btn_retry'] = 'Forsøg igen';
$lang['btn_skip'] = 'Spring over';
$lang['btn_abort'] = 'Afbryd';
$lang['legend'] = 'Flyt aktuelle side eller navnerum';
$lang['movepage'] = 'Flyt side';
$lang['movens'] = 'Flyt navnerum';
$lang['dst'] = 'Nyt navn:';
$lang['content_to_move'] = 'Indhold der skal flyttes:';
$lang['autoskip'] = 'Ignorer fejl, og spring over sider/filer der ikke kan flyttes';
$lang['autorewrite'] = 'Tilret links når flytning er fuldført';
$lang['move_pages'] = 'Sider';
$lang['move_media'] = 'Mediefiler';
$lang['move_media_and_pages'] = 'Sider og mediefiler';
$lang['nodst'] = 'Intet nyt navn angivet';
$lang['noaction'] = 'Der blev ikke defineret nogen flytninger';
$lang['renamepage'] = 'Omdøb side';
$lang['cantrename'] = 'Siden kan ikke omdøbes i øjeblikket. Prøv igen senere.';
$lang['js']['rename'] = 'Omdøb';
$lang['js']['cancel'] = 'Annuller';
$lang['js']['newname'] = 'Nyt navn:';
$lang['js']['inprogress'] = 'omdøber side og tilretter links...';
$lang['js']['complete'] = 'Flytningsoperation færdig.';
$lang['js']['renameitem'] = 'Omdøb denne';
$lang['js']['add'] = 'Opret et nyt navnerum';
$lang['js']['duplicate'] = 'Beklager, "%s" findes allerede i dette navnerum.';
$lang['root'] = '[Rod navnerum]';
$lang['noscript'] = 'Denne handling kræver JavaScript';
$lang['moveinprogress'] = 'Der er i øjeblikket en anden flytningsoperation i gang, du kan ikke anvende dette værktøj på dette tidspunkt.';
+10
View File
@@ -0,0 +1,10 @@
====== Flyt ======
Denne udvidelse gør dig i stand til at flytte og/eller omdøbe den aktuelle side, eller det aktuelle navnerum, med følgende restriktioner:
* Du skal have rettigheder til at redigere den aktuelle side/alle sider i det aktuelle navnerum
* Siderne der flyttes må ikke være låst pga. redigering
* For at flytte en side, skal du også have rettigheder til at oprette sider i det navnerum der flyttes til
* Du kan ikke flytte en side til et navnerum, hvor der allerede findes en side med samme navn.
Alle links til og fra sider der flyttes, vil blive tilrettet så de passer til den nye lokation og/eller det nye navn.
+3
View File
@@ -0,0 +1,3 @@
===== Flytning i gang... =====
Hold venligst denne side åben mens flytningen behandles.
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Jacob Palm <jacobpalmdk@icloud.com>
*/
$lang['allowrename'] = 'Tillad disse grupper og brugere at omdøbe sider (adskil med komma).';
$lang['minor'] = 'Markér tilretning af links som mindre rettelser? Mindre rettelser optræder ikke i RSS-feeds elller mails.';
$lang['autoskip'] = 'Slå overspring af fejl under flytning af navnerum til som standard';
$lang['autorewrite'] = 'Slå automatisk tilrettelse af links efter flytning af navnerum til som standard';
$lang['pagetools_integration'] = 'Tilføj omdøbningsknap til sideværktøjer';
+7
View File
@@ -0,0 +1,7 @@
===== Flytningshåndtering =====
Denne side gør dig i stand til at omarrangere din wikis navnerum, sider og mediefiler via træk og slip.
For at flytte mange navnerum, sider eller mediefiler til det samme navnerum, kan du benytte afkrydsningsfelter som følger:
* Marker de navnerum, sider og/eller mediefiler som du ønsker at flytte
* Træk et af de markerede elementer til den ønskede lokation, og alle øvrige markerede elementer flyttes automatisk med.
@@ -0,0 +1,71 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author F. Mueller-Donath <j.felix@mueller-donath.de>
*/
$lang['menu'] = 'Seite/Namensraum verschieben/umbenennen...';
$lang['inprogress'] = '(Verschiebung läuft gerade)';
$lang['treelink'] = 'Alternativ zu dieser einfachen Form können komplexere Umstrukturierungen des Wikis mit dem <a href="%s">baumbasierten Move-Manager</a> durchgeführt werden.';
$lang['notexist'] = 'Die Seite %s existiert nicht.';
$lang['norights'] = 'Du hast unzureichende Rechte um %s zu bearbeiten.';
$lang['filelocked'] = 'Die Seite %s ist gesperrt - bitte versuche es später noch einmal.';
$lang['notchanged'] = 'Kein Ziel für Seite %s angegeben (Ort bleibt unverändert).';
$lang['exists'] = 'Seite %s kann nicht nach %s verschoben werden, da das Ziel bereits existiert.';
$lang['notargetperms'] = 'Du hast nicht die Berechtigung, die Seite %s anzulegen.';
$lang['medianotexist'] = 'Die Mediendatei %s existiert nicht';
$lang['nomediarights'] = 'Du hast unzureichende Rechte, um die Mediendatei %s zu löschen.';
$lang['medianotchanged'] = 'Kein Ziel für Seite %s angegeben (Ort bleibt unverändert).';
$lang['mediaexists'] = 'Mediendatei %s kann nicht nach %s verschoben werden, da das Ziel bereits existiert.';
$lang['nomediatargetperms'] = 'Du hast keine Berechtigung, die Mediendatei %s anzulegen.';
$lang['extensionchange'] = 'Die Dateierweiterungen der alten und der neuen Datei sind unterschiedlich.';
$lang['indexerror'] = 'Fehler während der Aktualisierung des Suchindexes %s';
$lang['metamoveerror'] = 'Die Metadateien der Seite %s konnten nicht verschoben werden';
$lang['atticmoveerror'] = 'Die Attic-Dateien der Seite %s konnten nicht verschoben werden. Bitte verschiebe Sie sie manuell.';
$lang['mediametamoveerror'] = 'Die Metadateien der Mediendatei %s konnten nicht verschoben werden';
$lang['mediamoveerror'] = 'Verschieben der Mediendatei %s fehlgeschlagen';
$lang['mediaatticmoveerror'] = 'Die Attic-Dateien der Mediendatei %s konnten nicht verschoben werden. Bitte verschiebe sie manuell.';
$lang['renamed'] = 'Seitename wurde von %s auf %s geändert';
$lang['moved'] = 'Seite von %s nach %s verschoben';
$lang['move_rename'] = 'Seite von %s nach %s verschoben und umbenannt';
$lang['delete'] = 'Gelöscht durch das move Plugin';
$lang['linkchange'] = 'Links angepasst weil Seiten im Wiki verschoben wurden';
$lang['intro'] = 'Die Verschiebung wurde noch nicht gestartet!';
$lang['preview'] = 'Vorschau der Änderungen, die ausgeführt werden sollen ';
$lang['inexecution'] = 'Eine vorherige Verschiebung wurde nicht beendet - benutze die Knöpfe unten um die Verschiebung fortzusetzen oder abzubrechen. ';
$lang['btn_start'] = 'Start';
$lang['btn_continue'] = 'Fortsetzen';
$lang['btn_retry'] = 'Element wiederholen';
$lang['btn_skip'] = 'Element überspringen';
$lang['btn_abort'] = 'Abbrechen';
$lang['legend'] = 'Aktuelle Seite oder Namensraum verschieben';
$lang['movepage'] = 'Seite verschieben';
$lang['movens'] = 'Namensraum verschieben';
$lang['dst'] = 'Neuer Name:';
$lang['content_to_move'] = 'Zu verschiebender Inhalt:';
$lang['autoskip'] = 'Zu verschiebender Inhalt:';
$lang['autorewrite'] = 'Links anpassen, nachdem die Verschiebung abgeschlossen wurde';
$lang['move_pages'] = 'Seiten';
$lang['move_media'] = 'Mediandateien';
$lang['move_media_and_pages'] = 'Seiten und Mediendateien';
$lang['nodst'] = 'Kein neuer Name angegeben';
$lang['noaction'] = 'Es wurden keine Verschiebungen angegeben';
$lang['renamepage'] = 'Seite umbenennen';
$lang['notallowed'] = 'Du hast unzureichende Rechte, um Seiten oder Medien umzubenennen.';
$lang['cantrename'] = 'Auf die Seite kann zur Zeit nicht zugegriffen werden - bitte versuche es später noch einmal.';
$lang['js']['rename'] = 'Umbenennen';
$lang['js']['cancel'] = 'Abbrechen';
$lang['js']['newname'] = 'Neuer Name:';
$lang['js']['inprogress'] = 'Benenne Seite um und passe Links an...';
$lang['js']['complete'] = 'Verschieben abgeschlossen.';
$lang['js']['renameitem'] = 'Dieses Element umbenennen';
$lang['js']['add'] = 'Neuen Namensraum erstellen';
$lang['js']['duplicate'] = 'Entschuldigung, "%s" existiert in diesem Namensraum bereits. ';
$lang['root'] = '[Oberster Namensraum]';
$lang['noscript'] = 'Dieses Feature benötigt JavaScript.';
$lang['moveinprogress'] = 'Eine andere Verschiebeoperation läuft momentan, du kannst dieses Tool gerade nicht benutzen.';
// Media Manager
$lang['js']['moveButton'] = 'Datei verschieben / umbenennen';
$lang['js']['dialogIntro'] = 'Neuer Dateiname. Du kannst den Namensraum ändern, aber nicht die Dateierweiterung.';
@@ -0,0 +1,11 @@
====== Seite/Namensraum verschieben/umbenennen ======
Mit diesem Plugin kann die aktuelle Seite oder ein gesamter Namensraum verschoben oder umbenannt werden.
Folgende Einschränkungen/Bedingungen gelten:
* Sie müssen die Bearbeiten-Rechte für die Seite/alle Seiten im aktuellen Namensraum haben.
* Die Seiten, die verschoben werden, dürfen nicht gesperrt sein, d.h. sich im Bearbeitungsmodus befinden.
* Um eine Seite zu verschieben, benötigt man das Erstellen-Recht im Ziel-Namensraum.
* Eine Seite kann nicht in einen Namensraum verschoben werden, in der bereits eine Seite gleichen Namens existiert.
Alle Links von und auf die Seite werden aktualisiert, um dem neuen Namen bzw. dem neuen Namensraum zu entsprechen.
@@ -0,0 +1,3 @@
====== Verschiebung läuft... ======
Bitte lassen Sie diese Seite geöffnet, während die Verschiebung läuft.
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author F. Mueller-Donath <j.felix@mueller-donath.de>
*/
$lang['allowrename'] = 'Umbenennen von Seiten und Mediendateien diesen Gruppen und Benutzern erlauben (durch Kommas getrennt).';
$lang['minor'] = 'Linkanpassung als kleine Änderung markieren? Kleine Änderungen werden in RSS Feeds und Benachrichtigungsmails nicht aufgeführt.';
$lang['autoskip'] = 'Automatisches Überspringen von Fehlern beim Verschieben von Namensräumen standardmäßig aktivieren. ';
$lang['autorewrite'] = 'Automatische Linkanpassung standardmäßig aktivieren.';
$lang['pagetools_integration'] = 'Umbenennen-Button zu Pagetools hinzufügen';
@@ -0,0 +1,3 @@
====== Move-Manager =====
Diese Ansicht ermöglicht die Restrukturierung von Namensräumen, Seiten und Mediendateien des Wikis per Drag'n'Drop.
+73
View File
@@ -0,0 +1,73 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author picsar
* @author e-dschungel <github@e-dschungel.de>
* @author F. Mueller-Donath <j.felix@mueller-donath.de>
*/
$lang['menu'] = 'Seite/Namensraum verschieben/umbenennen...';
$lang['inprogress'] = '(Verschiebung läuft gerade)';
$lang['treelink'] = 'Alternativ zu dieser einfachen Form können komplexere Umstrukturierungen des Wikis mit dem <a href="%s">baumbasierten Move-Manager</a> durchgeführt werden.';
$lang['notexist'] = 'Die Seite %s existiert nicht.';
$lang['norights'] = 'Sie haben unzureichende Rechte um %s zu bearbeiten.';
$lang['filelocked'] = 'Die Seite %s ist gesperrt - versuchen Sie es später noch einmal.';
$lang['notchanged'] = 'Kein Ziel für Seite %s angegeben (Ort bleibt unverändert).';
$lang['exists'] = 'Seite %s kann nicht nach %s verschoben werden, da das Ziel bereits existiert.';
$lang['notargetperms'] = 'Sie haben nicht die Berechtigung, die Seite %s anzulegen.';
$lang['medianotexist'] = 'Die Mediendatei %s existiert nicht';
$lang['nomediarights'] = 'Sie haben unzureichende Rechte, um die Mediendatei %s zu löschen.';
$lang['medianotchanged'] = 'Kein Ziel für Seite %s angegeben (Ort bleibt unverändert).';
$lang['mediaexists'] = 'Mediendatei %s kann nicht nach %s verschoben werden, da das Ziel bereits existiert.';
$lang['nomediatargetperms'] = 'Sie haben nicht die Berechtigung, die Mediendatei %s anzulegen.';
$lang['extensionchange'] = 'Die Dateierweiterungen der alten und der neuen Datei sind unterschiedlich.';
$lang['indexerror'] = 'Fehler während der Aktualisierung des Suchindexes %s';
$lang['metamoveerror'] = 'Die Metadateien der Seite %s konnten nicht verschoben werden';
$lang['atticmoveerror'] = 'Die Attic-Dateien der Seite %s konnten nicht verschoben werden. Bitte verschieben Sie sie manuell.';
$lang['mediametamoveerror'] = 'Die Metadateien der Mediendatei %s konnten nicht verschoben werden';
$lang['mediamoveerror'] = 'Verschieben der Mediendatei %s fehlgeschlagen';
$lang['mediaatticmoveerror'] = 'Die Attic-Dateien der Mediendatei %s konnten nicht verschoben werden. Bitte verschieben Sie sie manuell.';
$lang['renamed'] = 'Seitename wurde von %s auf %s geändert';
$lang['moved'] = 'Seite von %s nach %s verschoben';
$lang['move_rename'] = 'Seite von %s nach %s verschoben und umbenannt';
$lang['delete'] = 'Gelöscht durch das move Plugin';
$lang['linkchange'] = 'Links angepasst, weil Seiten im Wiki verschoben wurden';
$lang['intro'] = 'Die Verschiebung wurde noch nicht gestartet!';
$lang['preview'] = 'Vorschau der Änderungen, die ausgeführt werden sollen ';
$lang['inexecution'] = 'Eine vorherige Verschiebung wurde nicht beendet - benutzen Sie die Knöpfe unten um die Verschiebung fortzusetzen oder abzubrechen. ';
$lang['btn_start'] = 'Start';
$lang['btn_continue'] = 'Fortsetzen';
$lang['btn_retry'] = 'Element wiederholen';
$lang['btn_skip'] = 'Element überspringen';
$lang['btn_abort'] = 'Abbrechen';
$lang['legend'] = 'Aktuelle Seite oder aktueller Namensraum';
$lang['movepage'] = 'Seite verschieben';
$lang['movens'] = 'Namensraum verschieben';
$lang['dst'] = 'Neuer Name:';
$lang['content_to_move'] = 'Zu verschiebender Inhalt:';
$lang['autoskip'] = 'Fehler ignorieren und Seiten oder Dateien, die nicht verschoben werden können, überspringen';
$lang['autorewrite'] = 'Links anpassen, nachdem die Verschiebung abgeschlossen wurde';
$lang['move_pages'] = 'Seiten';
$lang['move_media'] = 'Mediendateien';
$lang['move_media_and_pages'] = 'Seiten und Mediendateien';
$lang['nodst'] = 'Kein neuer Name angegeben';
$lang['noaction'] = 'Es wurden keine Verschiebungen angegeben';
$lang['renamepage'] = 'Seite umbenennen';
$lang['notallowed'] = 'Sie haben unzureichende Rechte, um Seiten oder Medien umzubenennen.';
$lang['cantrename'] = 'Auf die Seite kann zur Zeit nicht zugegriffen werden - versuchen Sie es später noch einmal.';
$lang['js']['rename'] = 'Umbenennen';
$lang['js']['cancel'] = 'Abbrechen';
$lang['js']['newname'] = 'Neuer Name:';
$lang['js']['inprogress'] = 'Benenne Seite um und passe Links an...';
$lang['js']['complete'] = 'Verschieben abgeschlossen.';
$lang['js']['renameitem'] = 'Dieses Element umbenennen';
$lang['js']['add'] = 'Neuen Namensraum erstellen';
$lang['js']['duplicate'] = 'Entschuldigung, "%s" existiert in diesem Namensraum bereits. ';
$lang['root'] = '[Oberster Namensraum]';
$lang['noscript'] = 'Dieses Feature benötigt JavaScript.';
$lang['moveinprogress'] = 'Eine andere Verschiebeoperation läuft momentan, Sie können dieses Tool gerade nicht benutzen.';
// Media Manager
$lang['js']['moveButton'] = 'Datei verschieben / umbenennen';
$lang['js']['dialogIntro'] = 'Neuer Dateiname. Sie können den Namensraum ändern, aber nicht die Dateierweiterung.';
+11
View File
@@ -0,0 +1,11 @@
====== Seite/Namensraum verschieben/umbenennen ======
Mit diesem Plugin kann die aktuelle Seite oder ein gesamter Namensraum verschoben oder umbenannt werden.
Folgende Einschränkungen/Bedingungen gelten:
* Sie müssen die Bearbeiten-Rechte für die Seite/alle Seiten im aktuellen Namensraum haben.
* Die Seiten, die verschoben werden, dürfen nicht gesperrt sein, d.h. sich im Bearbeitungsmodus befinden.
* Um eine Seite zu verschieben, benötigt man das Erstellen-Recht im Ziel-Namensraum.
* Eine Seite kann nicht in einen Namensraum verschoben werden, in der bereits eine Seite gleichen Namens existiert.
Alle Links von und auf die Seite werden aktualisiert, um dem neuen Namen bzw. dem neuen Namensraum zu entsprechen.
+3
View File
@@ -0,0 +1,3 @@
====== Verschiebung läuft... ======
Bitte lassen Sie diese Seite geöffnet, während die Verschiebung läuft.
+13
View File
@@ -0,0 +1,13 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author F. Mueller-Donath <j.felix@mueller-donath.de>
* @author e-dschungel <github@e-dschungel.de>
*/
$lang['allowrename'] = 'Umbenennen von Seiten und Mediendateien diesen Gruppen und Benutzern erlauben (durch Kommas getrennt).';
$lang['minor'] = 'Linkanpassung als kleine Änderung markieren? Kleine Änderung werden in RSS Feeds und Benachrichtigungsmails nicht aufgeführt.';
$lang['autoskip'] = 'Automatisches Überspringen von Fehlern beim Verschieben von Namensräumen standardmäßig aktivieren. ';
$lang['autorewrite'] = 'Automatische Linkanpassung standardmäßig aktivieren.';
$lang['pagetools_integration'] = 'Umbenennen-Button zu Pagetools hinzufügen';
+3
View File
@@ -0,0 +1,3 @@
====== Move-Manager =====
Diese Ansicht ermöglicht die Restrukturierung von Namensräumen, Seiten und Mediendateien des Wikis per Drag'n'Drop.
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Katerina Katapodi <katerinakatapodi@gmail.com>
*/
$lang['menu'] = 'Μετακινείστε σελίδες και κενά ονομάτων';
$lang['inprogress'] = '(μετακίνηση εκκρεμοτήτων)';
$lang['treelink'] = 'Κατ\'εναλλαγή προς αυτή την απλή φόρμα μπορείτε να ανοικοδομήστε το σύμπλεγμα wiki σας χρησιμοποιώντας <href=\'\'%s> tree-based move manager </a>';
$lang['notexist'] = 'Η σελίδα %s δεν υπάρχει';
$lang['norights'] = 'Δεν έχετε επαρκείς άδειες να εκδώσετε %s. ';
$lang['filelocked'] = 'Η σελίδα %s είναι κλειδωμένη. Παρακαλώ προσπαθήστε ξανά. ';
$lang['notchanged'] = 'Ο νέος προορισμός που δόθηκε για την σελίδα %s (η τοποθεσία δεν άλλαξε).';
$lang['exists'] = 'Η σελίδα δεν μπορεί να μετακινηθεί στο %s, ο προορισμός υπάρχει ήδη.';
$lang['notargetperms'] = 'Δεν έχετε την άδεια να δημιουργήσετε την σελίδα %s.';
$lang['medianotexist'] = 'Το αρχείο μέσων ενημέρωσης %s δεν υπάρχει';
$lang['nomediarights'] = 'Δεν έχετε άδεια να καταργήσετε το %s.';
$lang['medianotchanged'] = 'Ο νέος προορισμός που δόθηκε για την σελίδα %s (η θέση δεν άλλαξε)';
$lang['mediaexists'] = 'Τα μέσα %s δεν μπορούν να μετακινηθούν στο %s, ο προορισμός υπάρχει ήδη.';
$lang['nomediatargetperms'] = 'Δεν έχετε άδεια να δημιουργήσετε τον φάκελλο μέσων ενημέρωσης %s';
$lang['indexerror'] = 'Υπήρξε σφάλμα κατά την ενημέρωση του δείκτη %s.';
$lang['metamoveerror'] = '5Οι φάκελλοι meta της σελίδας %s δεν μπόρεσαν να μετακινηθούν';
$lang['atticmoveerror'] = 'Οι φάκελλοι attic της σελίδας %s δεν μπόρεσαν να μετακινηθούν. Παρακαλώ μετακινήστε τους με το χέρι.';
$lang['mediametamoveerror'] = 'Οι φάκελλοι meta του φακέλλου μέσων ενημέρωσης %s δεν μπόρεσαν να μετακινηθούν';
$lang['mediamoveerror'] = 'Η μετακίνηση του φακέλλου μέσων ενημέρωσης %s απέτυχε';
$lang['mediaatticmoveerror'] = 'Οι αττικοί φάκελλοι μέσων ενημέρωσης %s δεν μπόρεσαν να μετακινηθούν. Παρακαλώ μετακινήστε τους χειροκίνητα. ';
$lang['renamed'] = 'Το όνομα της σελίδας άλλαξε από %s σε %s ';
$lang['moved'] = 'Η σελίδα μετακινήθηκε από %s σε %s';
$lang['move_rename'] = 'H σελίδα μετακινήθηκε και μετονομάστηκε από %s σε %s';
$lang['delete'] = 'Διαγράφηκε μετακινώντας το plugin ';
$lang['linkchange'] = 'Οι σύνδεσμοι άλλαξαν λόγω μια διαδικασίας μετακίνησης';
$lang['intro'] = 'Η διαδικασία μετακίνησης δεν άρχισε ακόμη!';
$lang['preview'] = 'Δέστε τις αλλαγές που πρέπει να γίνουν.';
$lang['inexecution'] = 'Μια προηγούμενη κίνηση δεν ολοκληρώθηκε-χρησιμοποιείστε τα κουμπιά κάτω για να συνεχίσετε ή αφαιρέστε την διαδικασία.';
$lang['btn_start'] = 'Έναρξη ';
$lang['btn_continue'] = 'Συνεχίστε';
$lang['btn_retry'] = 'Ξαναπροσπαθήσετε ';
$lang['btn_skip'] = 'Παρακάμψετε θέμα';
$lang['btn_abort'] = 'Αφαίρεση';
$lang['legend'] = 'Μετακινείστε την παρούσα σελίδα ή τον χώρο ονόματος ';
$lang['movepage'] = 'Μετακινείστε την σελίδα';
$lang['movens'] = 'Μετακινείστε τον χώρο ονόματος ';
$lang['dst'] = 'Νέο όνομα:';
$lang['content_to_move'] = 'Περιεχόμενο προς μετακίνηση:';
$lang['autoskip'] = 'Αγνοήστε τα λάθη και παραλείψετε σελίδες ή φακέλλους που δεν μπορούν να μετακινηθούν';
$lang['autorewrite'] = 'Ξαναγράψετε συνδέσμους αφού ολοκληρωθεί η μετακίνηση';
$lang['move_pages'] = 'Σελίδες ';
$lang['move_media'] = 'Αρχεία μέσων ενημέρωσης';
$lang['move_media_and_pages'] = 'Σελίδες και αρχεία μέσων επικοινωνίας';
$lang['nodst'] = 'Δεν δόθηκε νέο όνομα';
$lang['noaction'] = 'Δεν βρέθηκαν αλλαγές';
$lang['renamepage'] = 'Μετονομάστε την Σελίδα ';
$lang['cantrename'] = 'Αυτή η σελίδα δεν μπορεί να μετονομαστεί τώρα. Παρακαλώ προσπαθήστε αργότερα.';
$lang['js']['rename'] = 'Μετονομάστε';
$lang['js']['cancel'] = 'Ακυρώστε';
$lang['js']['newname'] = 'Νέο όνομα :';
$lang['js']['inprogress'] = 'μετονομασία σελίδας και προσαρμογή συνδέσμων';
$lang['js']['complete'] = 'Η διαδικασία της μετακίνησης ολοκληρώθηκε';
$lang['js']['renameitem'] = 'Μετονομάστε αυτό το τεμάχιο';
$lang['js']['add'] = 'Δημιουργήστε ένα νέο χώρο ονόματος';
$lang['js']['duplicate'] = 'Λυπάμαι, το "%s" υπάρχει ήδη σε αυτό το χώρο ονόματος';
$lang['root'] = '{Βασικός χώρος ονόματος}';
$lang['noscript'] = 'Αυτό το χαρακτηριστικό χρειάζεται JavaScript';
$lang['moveinprogress'] = 'Υπάρχει μια άλλη διαδικασία μετακίνησης σε εξέλιξη τώρα, δεν μπορείτε να χρησιμοποιήστε αυτό το εργαλείο.';
+9
View File
@@ -0,0 +1,9 @@
====== Μετακίνηση ======
Αυτό το επιπρόσθετο σας επιτρέπει να μετακινήσετε και/ή μετονομάστε την παρούσα σελίδα ή μετακινήστε και/ή μετονομάστε τον τρέχοντα χώρο ονόματος στα πλαίσια των ακόλουθων περιορισμών:
* Πρέπει να έχετε άδεια έκδοσης για αυτήν την σελίδα/όλες τις σελίδες στο παρόντα κενό χώρο.
* Οι σελίδες που μετακινούνται δεν πρέπει να είναι κλειδωμένες για έκδοση.
* Για να μετακινήσετε μια σελίδα πρέπει επίσης να δημιουργήσετε 'άδεια' στον κενό χώρο ονομασίας.
* Δεν μπορείτε να μετακινήσετε μια σελίδα σε χώρο ονόματος όπου υπάρχει μια σελίδα με το ίδιο όνομα.
Όλες οι ιστοσελίδες από και προς τις σελίδες που μετακινούνται θα ενημερωθούν για να απεικονίσουν το νέο μέρος και/ή όνομα.
+2
View File
@@ -0,0 +1,2 @@
====== Μετακίνηση σε Εξέλιξη... ======
Παρακαλώ κρατήστε αυτήν την σελίδα ανοικτή κατά την διάρκεια της διαδικασίας εξέλιξης.
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Katerina Katapodi <katerinakatapodi@gmail.com>
*/
$lang['allowrename'] = 'Συμβάλλετε στην μετονομασία σελίδων σε αυτές τις ομάδες και χρήστες (χωρισμός με κόμμα).';
$lang['minor'] = 'Θέλετε να σημειώσετε τις ρυθμίσεις των ιστοσελίδων ως ελάσσονες? Οι ελάσσονες αλλαγές δεν θα συμπεριληφθούν στην λίστα των τροφοδοτήσεων RSS και στις εγγραφές με email.';
$lang['autoskip'] = 'Ενεργοποιείστε την αυτόματη παράλειψη λαθών σε αρχεία που μετακινείτε κατ\'επιλογήν.';
$lang['autorewrite'] = 'Ενεργοποιείστε το σύνδεσμο αυτόματης επανεγγραφής μετά τις μετακινήσεις αρχείων κατ\'επιλογήν.';
$lang['pagetools_integration'] = 'Προσθέσετε το πλήκτρο μετονομασίας στα εργαλεία σελίδων.';
+2
View File
@@ -0,0 +1,2 @@
====== Βασική Μετακίνηση =====
Αυτή η προβολή σας επιτρέπει να ρυθμίσετε εκ νέου τις ονομασίες αρχείων Wiki, φακέλλους σελίδων και μέσων ενημέρωσης μέσω του Drag'n Drop.
+88
View File
@@ -0,0 +1,88 @@
<?php
/**
* english language file
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author Gary Owen <>
*/
$lang['menu'] = 'Move pages and namespaces';
$lang['inprogress'] = '(move pending)';
$lang['treelink'] = 'Alternatively to this simple form you can manage complex restructuring of your wiki using the <a href="%s">tree-based move manager</a>.';
// page errors
$lang['notexist'] = 'The page %s does not exist';
$lang['norights'] = 'You have insufficient permissions to edit %s.';
$lang['filelocked'] = 'The page %s is locked. Try again later.';
$lang['notchanged'] = 'No new destination given for page %s (location unchanged).';
$lang['exists'] = 'Page %s can\'t be moved to %s, the target already exists.';
$lang['notargetperms'] = 'You don\'t have the permission to create the page %s.';
// media errors
$lang['medianotexist'] = 'The media file %s does not exist';
$lang['nomediarights'] = 'You have insufficient permissions to delete %s.';
$lang['medianotchanged'] = 'No new destination given for page %s (location unchanged).';
$lang['mediaexists'] = 'Media %s can\'t be moved to %s, the target already exists.';
$lang['nomediatargetperms'] = 'You don\'t have the permission to create the media file %s.';
$lang['extensionchange'] = 'Extension of the new file is not the same as the original.';
// system errors
$lang['indexerror'] = 'Error while updating the search index %s';
$lang['metamoveerror'] = 'The meta files of page %s couldn\'t be moved';
$lang['atticmoveerror'] = 'The attic files of page %s couldn\'t be moved. Please move them manually.';
$lang['mediametamoveerror'] = 'The meta files of the media file %s couldn\'t be moved';
$lang['mediamoveerror'] = 'Moving the media file %s failed';
$lang['mediaatticmoveerror'] = 'The attic files of media file %s couldn\'t be moved. Please move them manually.';
// changelog summaries
$lang['renamed'] = 'Page name changed from %s to %s';
$lang['moved'] = 'Page moved from %s to %s';
$lang['move_rename'] = 'Page moved and renamed from %s to %s';
$lang['delete'] = 'Deleted by move plugin';
$lang['linkchange'] = 'Links adapted because of a move operation';
// progress view
$lang['intro'] = 'The move operation has not been started, yet!';
$lang['preview'] = 'Preview changes to be executed.';
$lang['inexecution'] = 'A previous move was not completed - use the buttons below to continue or abort the execution.';
$lang['btn_start'] = 'Start';
$lang['btn_continue'] = 'Continue';
$lang['btn_retry'] = 'Retry item';
$lang['btn_skip'] = 'Skip item';
$lang['btn_abort'] = 'Abort';
// Form labels
$lang['legend'] = 'Move current page or namespace';
$lang['movepage'] = 'Move page';
$lang['movens'] = 'Move namespace';
$lang['dst'] = 'New name:';
$lang['content_to_move'] = 'Content to move:';
$lang['autoskip'] = 'Ignore errors and skip pages or files that can\'t be moved';
$lang['autorewrite'] = 'Rewrite links right after the move completed';
$lang['move_pages'] = 'Pages';
$lang['move_media'] = 'Media files';
$lang['move_media_and_pages'] = 'Pages and media files';
$lang['nodst'] = 'No new name given';
$lang['noaction'] = 'There were no moves defined';
// Rename feature
$lang['renamepage'] = 'Rename Page';
$lang['cantrename'] = 'The page can\'t be renamed right now. Please try later.';
$lang['notallowed'] = 'You are not allowed to rename pages or media.';
$lang['js']['rename'] = 'Rename';
$lang['js']['cancel'] = 'Cancel';
$lang['js']['newname'] = 'New name:';
$lang['js']['inprogress'] = 'renaming page and adjusting links...';
$lang['js']['complete'] = 'Move operation finished.';
// Tree Manager
$lang['root'] = '[Root namespace]';
$lang['noscript'] = 'This feature requires JavaScript';
$lang['moveinprogress'] = 'There is another move operation in progress currently, you can\'t use this tool right now.';
$lang['js']['renameitem'] = 'Rename this item';
$lang['js']['add'] = 'Create a new namespace';
$lang['js']['duplicate'] = 'Sorry, "%s" already exists in this namespace.';
// Media Manager
$lang['js']['moveButton'] = 'Move file';
$lang['js']['dialogIntro'] = 'Enter new file destination. You may change the namespace but not the file extension.';
+10
View File
@@ -0,0 +1,10 @@
====== Move ======
This plugin allows you to move and/or rename the current page or move and/or rename the current namespace within the following restrictions:
* You must have edit permission for the current page/all pages in the current namespace.
* The pages that are moved must not be locked for editing.
* For moving a page you also need create permission in the target namespace.
* You cannot move a page to a namespace where a page with the same name already exists.
All links to and from the pages that are moved will be updated to reflect the new location and/or name.
+3
View File
@@ -0,0 +1,3 @@
====== Move in Progress... ======
Please keep this page open while the move progresses.
+7
View File
@@ -0,0 +1,7 @@
<?php
$lang['allowrename'] = 'Allow renaming of pages and media to these groups and users (comma separated).';
$lang['minor'] = 'Mark link adjustments as minor? Minor changes will not be listed in RSS feeds and subscription mails.';
$lang['autoskip'] = 'Enable automatic skipping of errors in namespace moves by default.';
$lang['autorewrite'] = 'Enable automatic link rewriting after namespace moves by default.';
$lang['pagetools_integration'] = 'Add renaming button to pagetools';
+7
View File
@@ -0,0 +1,7 @@
====== Move Manager =====
This interface allows you to rearrange your wiki's namespaces, pages and media files via Drag'n'Drop.
In order to move many namespaces, pages or media files to the same destination, you can use the checkboxes as follows:
* check the namespaces, pages or media files you want to move;
* move one of the checked items to the desired destination, all selected items will be moved to this destination.
+66
View File
@@ -0,0 +1,66 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Gary Owen
* @author Domingo Redal <docxml@gmail.com>
*/
$lang['menu'] = 'Mover/Renombrar página...';
$lang['inprogress'] = '(pendientes de mover)';
$lang['treelink'] = 'Como alternativa a este sencillo formulario, puede gestionar una reestructuración compleja de su wiki utilizando el <a href="%s">administrador para mover páginas basado en listas desplegables</a>.';
$lang['notexist'] = 'La página %s aún no existe';
$lang['norights'] = 'No tiene permisos suficientes para editar %s.';
$lang['filelocked'] = 'La página %s está bloqueada. Inténtalo de nuevo más tarde.';
$lang['notchanged'] = 'No se ha indicado un destino nuevo para la página %s (ubicación sin cambios).';
$lang['exists'] = 'La página %s no se puede mover a %s, ya existe el destino.';
$lang['notargetperms'] = 'No tienes permisos para crear la página %s.';
$lang['medianotexist'] = 'El fichero multimedia %s no existe';
$lang['nomediarights'] = 'No tiene permisos suficientes para borrar %s.';
$lang['medianotchanged'] = 'No se ha indicado un destino nuevo para la página %s (ubicación sin cambios).';
$lang['mediaexists'] = 'El fichero multimedia %s no se puede mover a %s, ya existe el destino.';
$lang['nomediatargetperms'] = 'No tienes permisos para crear el fichero multimedia %s.';
$lang['indexerror'] = 'Error al actualizar el índice de búsqueda %s';
$lang['metamoveerror'] = 'Los ficheros meta de la página %s no se pudieron mover';
$lang['atticmoveerror'] = 'Los ficheros attic de la página %s no se pudieron mover. Por favor, muévalos manualmente.';
$lang['mediametamoveerror'] = 'Los ficheros meta del fichero multimedia %s no se pudieron mover';
$lang['mediamoveerror'] = 'Se ha producido un error al mover el fichero multimedia %s';
$lang['mediaatticmoveerror'] = 'Los ficheros attic del fichero multimedia %s no se pudieron mover. Por favor, muévalos manualmente.';
$lang['renamed'] = 'El nombre de la página cambió de %s a %s';
$lang['moved'] = 'Página movida de %s a %s';
$lang['move_rename'] = 'Página movida y renombrada de %s a %s';
$lang['delete'] = 'Borrado por la extensión move';
$lang['linkchange'] = 'Enlaces adaptados debido a una operación de mover';
$lang['intro'] = '¡La operación de mover aún no se ha iniciado!';
$lang['preview'] = 'Previsualizar los cambios a ejecutar.';
$lang['inexecution'] = 'Una operación de mover anterior no se completó - utilice los botones de abajo para continuar o anular la ejecución.';
$lang['btn_start'] = 'Empezar';
$lang['btn_continue'] = 'Continuar';
$lang['btn_retry'] = 'Reintentar elemento';
$lang['btn_skip'] = 'Saltar elemento';
$lang['btn_abort'] = 'Anular';
$lang['legend'] = 'Mover la página actual o el espacio de nombres';
$lang['movepage'] = 'Mover la página';
$lang['movens'] = 'Mover el espacio de nombres';
$lang['dst'] = 'Nuevo nombre:';
$lang['content_to_move'] = 'Contenido para mover:';
$lang['autoskip'] = 'Ignorar errores y omitir páginas o ficheros que no se pueden mover';
$lang['autorewrite'] = 'Reescribir los enlaces justo después de completar la operación de mover';
$lang['move_pages'] = 'Páginas';
$lang['move_media'] = 'Ficheros multimedia';
$lang['move_media_and_pages'] = 'Páginas y ficheros multimedia';
$lang['nodst'] = 'No se ha dado ningún nombre nuevo';
$lang['noaction'] = 'No hubo operaciones de mover definidas';
$lang['renamepage'] = 'Cambiar nombre de página';
$lang['cantrename'] = 'No se puede cambiar el nombre de la página en este momento. Inténtalo de nuevo más tarde.';
$lang['js']['rename'] = 'Renombrar';
$lang['js']['cancel'] = 'Cancelar';
$lang['js']['newname'] = 'Nuevo nombre:';
$lang['js']['inprogress'] = 'cambiar el nombre de la página y ajustar los enlaces...';
$lang['js']['complete'] = 'La operación de mover ha finalizado.';
$lang['js']['renameitem'] = 'Renombrar este elemento';
$lang['js']['add'] = 'Crear un nuevo espacio de nombres';
$lang['js']['duplicate'] = 'Lo sentimos, "%s" ya existe en este espacio de nombres.';
$lang['root'] = '[Espacio de nombres raíz]';
$lang['noscript'] = 'Esta función requiere JavaScript';
$lang['moveinprogress'] = 'Hay otra operación de mover actualmente en curso, no se puede usar esta herramienta ahora mismo.';
+10
View File
@@ -0,0 +1,10 @@
====== Mover ======
Esta extensión le permite mover y/o renombrar el documento actual respetando las siguientes restricciones.
* Debe tener permisos de edición sobre la página actual.
* La página actual no puede ser bloqueada para la edición.
* Para mover una página también necesita permiso de creación sobre el directorio de destino.
* No puede mover la página a un espacio de nombres donde ya existe una página con el mismo nombre.
Todos los enlaces desde y hacia esta página serán actualizados para reflejar la nueva ubicación y/o nombre.
+3
View File
@@ -0,0 +1,3 @@
====== Mover en progreso... ======
Por favor, mantenga esta página abierta mientras progresa la operación de mover.
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Domingo Redal <docxml@gmail.com>
*/
$lang['allowrename'] = 'Permitir el cambio de nombre de páginas a estos grupos y usuarios (separados por comas).';
$lang['minor'] = '¿Marcar los ajustes de enlace como cambios menores? Los cambios menores no se incluirán en los feeds RSS ni en los correos de suscripción.';
$lang['autoskip'] = 'Habilitar de forma predeterminada el salto automático de errores en las operaciones de mover el espacio de nombres.';
$lang['autorewrite'] = 'Habilitar de forma predeterminada la reescritura automática de enlaces después de mover el espacio de nombres.';
$lang['pagetools_integration'] = 'Añadir botón de cambio de nombre a las herramientas de página';
+3
View File
@@ -0,0 +1,3 @@
====== Administrador de mover =====
Esta interfaz le permite reorganizar los espacios de nombres, páginas y ficheros multimedia de su wiki a través de arrastrar y soltar (Drag'n'Drop).
+71
View File
@@ -0,0 +1,71 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Schplurtz le Déboulonné <schplurtz@laposte.net>
* @author Gary Owen
* @author Nicolas Friedli <nicolas@theologique.ch>
*/
$lang['menu'] = 'Déplacer/Renommer pages et catégories...';
$lang['inprogress'] = '(déplacement en attente)';
$lang['treelink'] = 'Au lieu de ce simple formulaire, vous pouvez effectuer des restructurations complexes de votre wiki en utilisant le <a href="%s">gestionnaire de déplacements par arborescence</a>';
$lang['notexist'] = 'La page %s n\'existe pas encore';
$lang['norights'] = 'Vos permissions sont insufisante pour éditer %s.';
$lang['filelocked'] = 'La page %s est verrouillée - réessayez plus tard.';
$lang['notchanged'] = 'Pas de nouvelle destination pour la page %s (emplacement inchangé).';
$lang['exists'] = 'La page %s ne peut être déplacée vers %s, la cible existe déjà.';
$lang['notargetperms'] = 'Pous n\'avez pas la permission de créer la page %s.';
$lang['medianotexist'] = 'Le fichier média %s n\'existe pas.';
$lang['nomediarights'] = 'Vous ne disposez pas des permissions suffisantes pour effacer %s.';
$lang['medianotchanged'] = 'Pas de nouvelle destination pour la page %s (emplacement inchangé).';
$lang['mediaexists'] = 'Impossible de déplacer le média %s. la cible %s existe déjà.';
$lang['nomediatargetperms'] = 'Vous n\'avez pas les permissions de créer le média %s';
$lang['extensionchange'] = 'L\'extension du nouveau fichier diffère de celle de l\'original.';
$lang['indexerror'] = 'Erreur lors de la mise à jour de l\'index de recherche %s.';
$lang['metamoveerror'] = 'Impossible de déplacer les métafichiers de la page %s.';
$lang['atticmoveerror'] = 'L\'historique (attic) de la page %s ne peut être déplacé. Veuillez déplacer les fichiers manuellement.';
$lang['mediametamoveerror'] = 'Impossible de déplacer les métafichiers du media %s.';
$lang['mediamoveerror'] = 'Échec du déplacement du média %s.';
$lang['mediaatticmoveerror'] = 'L\'historique (attic) du média %s ne peut être déplacé. Veuillez déplacer les fichiers manuellement.';
$lang['renamed'] = 'Nom de la page changé de %s à %s';
$lang['moved'] = 'Page déplacée de %s à %s';
$lang['move_rename'] = 'Page déplacée et renommée de %s à %s';
$lang['delete'] = 'Effacé par le plugin de déplacement';
$lang['linkchange'] = 'Liens modifiés en raison d\'un déplacement.';
$lang['intro'] = 'L\'opération de déplacement n\'a pas encore commencé.';
$lang['preview'] = 'Visualiser les changements à effectuer.';
$lang['inexecution'] = 'Un déplacement n\'est pas arrivé à son terme - utilisez les boutons ci-dessous pour continuer ou abandonner son exécution.';
$lang['btn_start'] = 'Commencer';
$lang['btn_continue'] = 'Continuer';
$lang['btn_retry'] = 'Réessayer cette étape';
$lang['btn_skip'] = 'Passer cette étape';
$lang['btn_abort'] = 'Abandonner';
$lang['legend'] = 'Déplacer la page ou l\'espace de nom courant';
$lang['movepage'] = 'Déplacer la page';
$lang['movens'] = 'Déplacer l\'espace de nom';
$lang['dst'] = 'Nouveau nom:';
$lang['content_to_move'] = 'Contenu à déplacer:';
$lang['autoskip'] = 'Ignorer les erreurs et passer les pages ou fichiers qui ne peuvent être déplacés.';
$lang['autorewrite'] = 'Récrire les liens à l\'issue du déplacement.';
$lang['move_pages'] = 'Pages';
$lang['move_media'] = 'Fichiers média';
$lang['move_media_and_pages'] = 'Pages et fichiers média';
$lang['nodst'] = 'Pas de nouveau nom donné';
$lang['noaction'] = 'Pas de déplacement demandé';
$lang['renamepage'] = 'Renommer la page';
$lang['cantrename'] = 'Impossible de renommer la page maintenant. Veuillez essayer plus tard.';
$lang['notallowed'] = 'Vous n\'êtes pas autorisé à renommer les pages ou les médias.';
$lang['js']['rename'] = 'Renommer';
$lang['js']['cancel'] = 'Annuler';
$lang['js']['newname'] = 'Nouveau nom:';
$lang['js']['inprogress'] = 'Renommage des pages et ajustement des pages en cours...';
$lang['js']['complete'] = 'Déplacement effectué.';
$lang['js']['renameitem'] = 'Renommer cet élément';
$lang['js']['add'] = 'Créer une nouvelle catégorie';
$lang['js']['duplicate'] = 'Désolé, "%s" existe dans cette catégorie.';
$lang['js']['moveButton'] = 'Déplacer le fichier.';
$lang['js']['dialogIntro'] = 'Entrez le nouvel emplacement du fichier. Vous pouvez changer la catégorie, mais pas l\'extension.';
$lang['root'] = '[Catégorie racine]';
$lang['noscript'] = 'Cette fonction requiert JavaScript';
$lang['moveinprogress'] = 'Une opération de déplacement est en cours en ce moment. Vous ne pouvez pas utiliser cet outil maintenant.';
+10
View File
@@ -0,0 +1,10 @@
====== Move ======
Cette extension permet de déplacer et/ou renommer le document courant ou la catégorie courante, avec les limitations suivantes :
* Il faut avoir les droits d'édition sur le document/tous les documents de la catégorie
* Les documents ne doivent pas être verrouillés pour l'édition
* Pour déplacer une page il faut également disposer du droit de création dans la catégorie de destination
* Il est impossible de déplacer le document vers une catégorie où un document du même nom existe déjà.
Tous les liens depuis et vers la page seront mis à jour pour refléter le nouvel emplacement et/ou le nouveau nom.
+3
View File
@@ -0,0 +1,3 @@
====== Déplacements en cours... ======
Veuillez garder cette page ouverte pendant toute la durée du déplacement.
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Schplurtz le Déboulonné <Schplurtz@laposte.net>
*/
$lang['allowrename'] = 'Autoriser le renommage de page à ces utilisateurs et groupes (utiliser des virgules)';
$lang['minor'] = 'Noter les ajustements de liens comme des modifications mineures. Les modifications mineures ne sont indiquées ni dans les flux RSS, ni dans les courriels des abonnements.';
$lang['autoskip'] = 'Par défaut, ignorer les erreurs de déplacement de catégories.';
$lang['autorewrite'] = 'Activer par défaut la ré-écriture automatique des liens après déplacement de catégories.';
$lang['pagetools_integration'] = 'Ajouter un bouton "renommage" aux outils de page';
+3
View File
@@ -0,0 +1,3 @@
====== Gestionnaire déplacement =====
Cette interface vous permet de réorganiser catégories, pages et médias de votre wiki par glisser-déposer.
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Davor Turkalj <turki.bsc@gmail.com>
*/
$lang['menu'] = 'Premještanje stranica i imenskih prostora';
$lang['inprogress'] = '(čekam premještanje)';
$lang['treelink'] = 'Umjesto ovog jednostavnog oblika možete raditi kompleksnu reorganizaciju vašeg wiki-a korištenjem <a href="%s">vizualnog upravitelja pomicanja</a>';
$lang['notexist'] = 'Stranica %s ne postoji';
$lang['norights'] = 'Nemate dovoljne ovlasti za uređivanje %s.';
$lang['filelocked'] = 'Stranica %s je zaključana. Pokušajte kasnije.';
$lang['notchanged'] = 'Za stranicu %s nije dana nova lokacija (lokacija nije promijenjena)';
$lang['exists'] = 'Stranica %s ne može biti pomaknuta na %s, odredište već postoji.';
$lang['notargetperms'] = 'Nemate ovlaštenja da kreirate stranicu %s.';
$lang['medianotexist'] = 'Medijska datoteka %s ne postoji';
$lang['nomediarights'] = 'Nemate dovoljna prava da obrišete %s.';
$lang['medianotchanged'] = 'Za stranicu %s nije dana nova lokacija (lokacija nije promijenjena)';
$lang['mediaexists'] = 'Medijska datoteka %s ne može biti pomaknuta na %s, odredište već postoji.';
$lang['nomediatargetperms'] = 'Nemate ovlaštenja da kreirate medijsku datoteku %s.';
$lang['indexerror'] = 'Greška pri izmjeni indeksa pretrage %s';
$lang['metamoveerror'] = 'Meta datoteke stranice %s ne mogu biti premještene';
$lang['atticmoveerror'] = 'Arhiva stranice (attic datoteke) %s ne može biti premještena. Molimo premjestite ju ručno.';
$lang['mediametamoveerror'] = 'Meta podaci medijske datoteke %s ne mogu biti premještene';
$lang['mediamoveerror'] = 'Neuspješno premještanje medijske datoteke %s';
$lang['mediaatticmoveerror'] = 'Arhiva (attic) medijske datoteke %s ne može biti premještena. Molimo premjestite ju ručno.';
$lang['renamed'] = 'Ime stranice promijenjeno iz %s u %s';
$lang['moved'] = 'Stranica premještena iz %s u %s';
$lang['move_rename'] = 'Stranica premještena i preimenovana iz %s u %s';
$lang['delete'] = 'Obrisano od strane dodatka za premještanje';
$lang['linkchange'] = 'Poveznice prilagođene zbog operacije premještanja';
$lang['intro'] = 'Operacija premještanja još nije počela!';
$lang['preview'] = 'Pregled izmjena koje će biti izvršene.';
$lang['inexecution'] = 'Prethodno premještanje nije završeno - upotrijebite tipke ispod za nastavak ili prekid izvršavanja.';
$lang['btn_start'] = 'Kreni';
$lang['btn_continue'] = 'Nastavi';
$lang['btn_retry'] = 'Ponovi stavku';
$lang['btn_skip'] = 'Preskoči stavku';
$lang['btn_abort'] = 'Prekini';
$lang['legend'] = 'Premjesti trenutnu stranicu ili imenski prostor';
$lang['movepage'] = 'Premjesti stranicu';
$lang['movens'] = 'Premjesti imenski prostor';
$lang['dst'] = 'Novo ime:';
$lang['content_to_move'] = 'Sadržaj za premjestiti:';
$lang['autoskip'] = 'Zanemari greške i preskoči stranice ili datoteke koje ne mogu biti premještene';
$lang['autorewrite'] = 'Izmijeniti poveznice odmah nakon završetka premještanja';
$lang['move_pages'] = 'Stranice';
$lang['move_media'] = 'Medijske datoteke';
$lang['move_media_and_pages'] = 'Stranice i medijske datoteke';
$lang['nodst'] = 'Nije uneseno novo ime';
$lang['noaction'] = 'Nema definiranih premještanja';
$lang['renamepage'] = 'Preimenuj stranicu';
$lang['cantrename'] = 'Stranica trenutno ne može biti preimenovana. Molimo pokušajte kasnije.';
$lang['js']['rename'] = 'Preimenuj';
$lang['js']['cancel'] = 'Prekini';
$lang['js']['newname'] = 'Novo ime:';
$lang['js']['inprogress'] = 'preimenovanje stranice i prilagodba poveznica...';
$lang['js']['complete'] = 'Operacija premještanja završila.';
$lang['js']['renameitem'] = 'Preimenuj ovu stavku';
$lang['js']['add'] = 'Kreiraj novi imenski prostor';
$lang['js']['duplicate'] = 'Isprika ali "%s" već postoji u ovom imenskom prostoru';
$lang['root'] = '[Korijen imenskog prostora]';
$lang['noscript'] = 'Ova osobina zahtijeva JavaScript';
$lang['moveinprogress'] = 'Trenutno je druga operacija premještanja u tijeku, zasada ne možete koristiti ovaj alat.';
+10
View File
@@ -0,0 +1,10 @@
====== Premjesti ======
Ovaj dodatak omogućava premještanje i/ili preimenovanje trenutne stranice ili imenskog prostora unutar slijedećih ograničenja:
* Morate imate dopuštenje za izmjenu trenutne ili svih stranicau trenutnom imenskom prostoru.
* Stranice koje se premještaju ne smiju biti zaključane.
* Za premještanje stranice također morate imati ovlaštenje za kreiranje u odredišnom imenskom prostoru.
* Na možete premjestiti stranicu u imenski prostor gdje stranica s istim imenom već postoji.
Sve poveznice na ili sa stranice koja se premješta biti će preusmjerene da pokazuju na novu lokaciju i/ili ime.
+3
View File
@@ -0,0 +1,3 @@
====== Premještanje u tijeku... ======
Molimo držite ovu stranicu otvorenom dok traje premještanje.
+13
View File
@@ -0,0 +1,13 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Davor Turkalj <turki.bsc@gmail.com>
*/
$lang['allowrename'] = 'Omogući preimenovanje stranica ovim grupama i korisnicima (zarezom odvojena lista).';
$lang['minor'] = 'Označiti prilagodbe poveznica kao manje značajne? Takve promjene neće biti prikazane u RSS obavijestima i obavijesnim porukama.';
$lang['autoskip'] = 'Omogući kao podrazumijevano automatsko preskakanje grešaka pri premještanju imenskog prostora.';
$lang['autorewrite'] = 'Omogući kao podrazumijevano automatsku prilagodbu poveznica.
';
$lang['pagetools_integration'] = 'Dodaj tipku za preimenovanje na alate stranice';
+4
View File
@@ -0,0 +1,4 @@
====== Upravitelj premještanja =====
Ovo sučelje omogućava reorganizaciju wiki imenskih prostora, stranica i medijskih datoteka korištenjem Povuci-i-Spusti radnje.
+62
View File
@@ -0,0 +1,62 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author NawanP <saya@nawan.my.id>
*/
$lang['menu'] = 'pindahkan halaman dan ruangnama';
$lang['notexist'] = 'Halaman %s tidak ada';
$lang['norights'] = 'Anda tidak memiliki izin untuk menyunting %s.';
$lang['filelocked'] = 'Halaman %s telah dikunci. Coba lagi nanti.';
$lang['notchanged'] = 'Tujuan baru tidak diberikan untuk halaman %s (lokasi halaman tidak berubah)';
$lang['exists'] = 'Halaman %s tidak dapat dipindahkan ke %s, target telah ada.';
$lang['notargetperms'] = 'Anda tidak memiliki izin untuk membuat halaman %s.';
$lang['medianotexist'] = 'Berkas %s tidak ada';
$lang['nomediarights'] = 'Anda tidak memiliki izin untuk menghapus %s.';
$lang['medianotchanged'] = 'Tidak ada tujuan yang dipilih untuk halaman %s (lokasi halaman tidak berubah).';
$lang['mediaexists'] = 'Media %s tidak dapat dipindahkan ke %s, target telah ada.';
$lang['nomediatargetperms'] = 'Anda tidak memiliki izin untuk mengunggah berkas %s.';
$lang['indexerror'] = 'Galat ketika memperbaharui indeks pencarian %s';
$lang['metamoveerror'] = 'Berkas meta halaman %s tidak dapat dipindahkan';
$lang['atticmoveerror'] = 'File attic halaman %s tidak dapat dipindahkan. Mohon pindahkan secara manual.';
$lang['mediametamoveerror'] = 'Berkas meta dari berkas media tidak dapat dipindahkan';
$lang['mediamoveerror'] = 'Gagal memindahkan berkas media %s';
$lang['mediaatticmoveerror'] = 'File attic dari berkas media %s tidak dapat dipindahkan. Mohon pindahkan secara manual.';
$lang['renamed'] = 'Nama halaman diubah dari %s menjadi %s';
$lang['moved'] = 'Halaman dipindahkan dari %s ke %s';
$lang['move_rename'] = 'Halaman dipindahkan dan diubah dari %s menjadi %s';
$lang['delete'] = 'Dihapus oleh move plugin';
$lang['linkchange'] = 'Pranala diubah karena operasi pemindahan';
$lang['intro'] = 'Operasi pemindahan belum dimulai!';
$lang['preview'] = 'Sedang mengeksekusi pratinjau perubahan.';
$lang['inexecution'] = 'Pemindahan sebelumnya belum selesai - gunakan tombol dibawah untuk melanjutkan atau membatalkan pemindahan.';
$lang['btn_start'] = 'Mulai';
$lang['btn_continue'] = 'Lanjutkan';
$lang['btn_retry'] = 'Coba butir';
$lang['btn_skip'] = 'Lewati butir';
$lang['btn_abort'] = 'Batalkan';
$lang['legend'] = 'Pindahkan halaman atau ruangnama terkini';
$lang['movepage'] = 'Pindahkan halaman';
$lang['movens'] = 'Pindahkan ruangnama';
$lang['dst'] = 'Nama baru:';
$lang['content_to_move'] = 'Konten untuk dipindahkan:';
$lang['autoskip'] = 'Abaikan galat dan lewati halaman atau berkas yang tidak dapat dipindahkan';
$lang['autorewrite'] = 'Ubah pranala setelah pemindahan selesai';
$lang['move_pages'] = 'Halaman';
$lang['move_media'] = 'Berkas media';
$lang['move_media_and_pages'] = 'Halaman dan berkas';
$lang['nodst'] = 'Tidak ada nama baru diberikan';
$lang['renamepage'] = 'Ubah nama halaman';
$lang['cantrename'] = 'Nama halaman tidak dapat diubah saat ini. Coba lagi nanti.';
$lang['js']['rename'] = 'Ubah nama';
$lang['js']['cancel'] = 'Batal';
$lang['js']['newname'] = 'Nama baru:';
$lang['js']['inprogress'] = 'mengubah nama halaman dan menyesuaikan pranala...';
$lang['js']['complete'] = 'Pemindahan selesai.';
$lang['js']['renameitem'] = 'Ubah nama item ini';
$lang['js']['add'] = 'Buat ruangnama baru';
$lang['js']['duplicate'] = 'Maaf, %s telah ada di ruangnama ini.';
$lang['root'] = '[Ruang nama root]';
$lang['noscript'] = 'Fitur ini membutuhkan JavaScript';
$lang['moveinprogress'] = 'Ada operasi pemindahan lain yang belum selesai, Anda tidak dapat menggunakan alat ini sekarang.';
+3
View File
@@ -0,0 +1,3 @@
====== Pemindahan dalam proses... ======
Mohon tetap di halaman ini saat pemindahan sedang diproses.
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author NawanP <saya@nawan.my.id>
*/
$lang['allowrename'] = 'Izinkan pengguna dan grup ini untuk mengubah nama halaman (pisahkan dengan koma).';
$lang['minor'] = 'Tandai penyesuaian pranala sebagai perubahan kecil? Perubahan kecil tidak akan terlihat di feed RSS dan milis.';
$lang['autoskip'] = 'Aktifkan lewati otomatis galat saat memindahkan ruangnama secara default.';
$lang['autorewrite'] = 'Aktifkan pengubahan pranala secara default saat memindahkan ruangnama.';
$lang['pagetools_integration'] = 'Tambahkan tombol ubah nama ke pagetools';
+7
View File
@@ -0,0 +1,7 @@
====== Move Manager =====
Antarmuka ini mengizinkan Anda untuk mengurutkan ulang ruangnama, halaman, dan berkas media dengan geser dan lepas.
Untuk memindahkan ruangnama, halaman, atau berkas sekaligus ke tujuan yang sama, Anda dapat menggunakan kotak centang sebagaimana dibawah ini:
* klik kotak centang pada ruangnama, halaman, atau berkas yang ingin Anda pindahkan;
* pindahkan satu dari butir yang telah dipilih ke tujuan yang diinginkan, semua butir yang dipilih secara otomatis akan dipindahkan ke tujuan tersebut.
+38
View File
@@ -0,0 +1,38 @@
<?php
/**
* italian language file
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author damiano <damiano@spagnuolo.eu>
* @author Dario Sguassero
*/
$lang['menu'] = 'Pagina/Namespace Sposta/Rinomina...';
$lang['inprogress'] = '(in sospeso)';
$lang['treelink'] = 'In alternativa a questo semplice modulo puoi gestire la ristrutturazione complessa della tua wiki usando il <a href="%s">tree-based gestore di movimento basato su albero </a>.';
$lang['notexist'] = 'La pagina %s non esiste';
$lang['norights'] = 'Non hai permessi sufficienti per modificare %s.';
$lang['filelocked'] = 'La pagina %s è bloccata. Riprova più tardi.';
$lang['notchanged'] = 'Nessuna nuova destinazione indicata per la pagina %s (posizione invariata).';
$lang['exists'] = 'La pagina% s non può essere spostata su %s, la destinazione esiste già.';
$lang['notargetperms'] = 'Non hai permessi sufficienti per creare la pagina %s.';
$lang['medianotexist'] = 'Il file media %s non esiste';
$lang['nomediarights'] = 'Non hai permessi sufficienti per cancellare %s.';
$lang['medianotchanged'] = 'Nessuna nuova destinazione indicata per la pagina %s (posizione invariata).';
$lang['mediaexists'] = 'Il supporto%s non può essere spostato su %s, la destinazione esiste già.';
$lang['nomediatargetperms'] = 'Non hai i permessi per creare il file media %s.';
$lang['indexerror'] = 'Errore durante l\'aggiornamento dell\'indice di ricerca %s';
$lang['metamoveerror'] = 'I meta file della pagina %s non possono essere spostati';
$lang['renamed'] = 'Il nome della pagina è stato cambiato da %s a %s';
$lang['moved'] = 'Pagina spostata da %s a %s';
$lang['move_rename'] = 'Pagina spostata e rinominata da %s a %s';
$lang['delete'] = 'Cancellato da move (sposta) plugin';
$lang['linkchange'] = 'Collegamento modificati a causa di un\'operazione di spostamento';
$lang['movepage'] = 'Sposta la pagina';
$lang['movens'] = 'Sposta il namespace';
$lang['content_to_move'] = 'Contenuto da spostare';
$lang['move_pages'] = 'Pagine';
$lang['move_media'] = 'File media';
$lang['move_media_and_pages'] = 'Pagine e file media';
$lang['root'] = '[Namespace radice]';
+10
View File
@@ -0,0 +1,10 @@
====== Move ======
Questo plugin ti permette di spostare e/o rinominare la pagina corrente o muovere e/o rinominare il namespace corrente, con le seguenti restrizioni:
* Devi avere i permessi di modificare la pagina corrente/tutte le pagine nel namespace corrente.
* Le pagine che verranno mosse non devono essere bloccate per un richiesta di modifica.
* Per muovere un pagina hai anche bisogno di creare i permessi nel namespace di destinazione.
* Non puoi muovere una pagina verso un namespace dove una pagina con lo stesso nome già esiste.
Tutti i collegamenti verso e dalle pagine che verranno mosse saranno aggiornate in coerenza con la nuova posizione e/o nome.
+65
View File
@@ -0,0 +1,65 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Hideaki SAWADA <chuno@live.jp>
*/
$lang['menu'] = 'ページ・名前空間の移動';
$lang['inprogress'] = '(移動保留中)';
$lang['treelink'] = 'この簡単なフォームの代わりに、<a href="%s">ツリー型の移動管理</a>を利用して Wiki の複雑な再構築を管理できます。';
$lang['notexist'] = '%s ページは存在しません。';
$lang['norights'] = '%s の編集権限がありません。';
$lang['filelocked'] = '%s ページはロックされています。後で再実行して下さい。';
$lang['notchanged'] = '%s ページの移動先が指定されていません(変更なし)。';
$lang['exists'] = '%s ページは %s に移動できません。既に存在します。';
$lang['notargetperms'] = '%s ページの作成権限がありません。';
$lang['medianotexist'] = '%s メディアファイルは存在しません。';
$lang['nomediarights'] = '%s の削除権限がありません。';
$lang['medianotchanged'] = '%s メディアファイルの移動先が指定されていません(変更なし)。';
$lang['mediaexists'] = '%s メディアファイルは %s に移動できません。既に存在します。';
$lang['nomediatargetperms'] = '%s メディアファイルの作成権限がありません。';
$lang['indexerror'] = '%s 検索インデックス更新中にエラーが発生しました。';
$lang['metamoveerror'] = '%s ページの meta ファイルが移動できませんでした。';
$lang['atticmoveerror'] = '%s ページの attic ファイルが移動できませんでした。手動で移動して下さい';
$lang['mediametamoveerror'] = '%s メディアファイルの meta ファイルが移動できませんでした。';
$lang['mediamoveerror'] = '%s メディアファイルが移動できませんでした。';
$lang['mediaatticmoveerror'] = '%s メディアファイルの attic ファイルが移動できませんでした。手動で移動して下さい。';
$lang['renamed'] = '%s から %s へページを名称変更しました。';
$lang['moved'] = '%s から %s へページを移動しました。';
$lang['move_rename'] = '%s から %s へページの移動と名称変更しました。';
$lang['delete'] = '移動プラグインが削除しました。';
$lang['linkchange'] = '移動操作に合わせてリンクを書き換えました。';
$lang['intro'] = '移動操作はまだ開始していません!';
$lang['preview'] = '実行する変更を事前確認して下さい。';
$lang['inexecution'] = '前の移動が完了していません。処理の続行・中止を下のボタンで指定して下さい。';
$lang['btn_start'] = '開始';
$lang['btn_continue'] = '続行';
$lang['btn_retry'] = '再実行';
$lang['btn_skip'] = 'スキップ';
$lang['btn_abort'] = '中止';
$lang['legend'] = '現在のページ・名前空間の移動';
$lang['movepage'] = 'ページの移動';
$lang['movens'] = '名前空間の移動';
$lang['dst'] = '移動先: ';
$lang['content_to_move'] = '移動する内容: ';
$lang['autoskip'] = 'エラーを無視し、移動できないページ・ファイルをスキップします。';
$lang['autorewrite'] = '移動完了後にリンクを書き換えます。';
$lang['move_pages'] = 'ページ';
$lang['move_media'] = 'メディアファイル';
$lang['move_media_and_pages'] = 'ページとメディアファイル';
$lang['nodst'] = '移動先が指定されていません。';
$lang['noaction'] = '移動操作が指定されていません。';
$lang['renamepage'] = 'ページの名称変更';
$lang['cantrename'] = 'ページを名称変更できません。後で再実行して下さい。';
$lang['js']['rename'] = '名称変更';
$lang['js']['cancel'] = '中止';
$lang['js']['newname'] = '新ページ名: ';
$lang['js']['inprogress'] = 'ページの名称変更・リンクの書き換え中…';
$lang['js']['complete'] = '名称変更操作が完了しました。';
$lang['js']['renameitem'] = 'この項目を名称変更します。';
$lang['js']['add'] = '新しい名前空間の作成';
$lang['js']['duplicate'] = '"%s" はこの名前空間内に既に存在します。';
$lang['root'] = '[ルート名前空間]';
$lang['noscript'] = 'この機能には JavaScriptが必要です。';
$lang['moveinprogress'] = '別の移動操作を処理中なので、今はこのツールを使用できません。';
+10
View File
@@ -0,0 +1,10 @@
====== 移動 ======
このプラグインは、以下の制約の範囲内で、今いるページの移動・名称変更、今いる名前空間の移動・名称変更が可能です:
* 今いるページ/今いる名前空間内の全ページに対する編集権限があること
* 移動するページが編集ロックされていないこと
* ページ移動のために、移動先の名前空間に対する作成権限があること
* 移動先の名前空間内に同じ名前のページが存在しないこと
移動したページとの間の全てのリンクは、新しい場所・新しい名前を反映して更新されます。
+3
View File
@@ -0,0 +1,3 @@
====== 移動処理中・・・ ======
移動処理中は、このページを閉じないで下さい。
+12
View File
@@ -0,0 +1,12 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Hideaki SAWADA <chuno@live.jp>
*/
$lang['allowrename'] = 'ページ名変更を許可するグループ・ユーザー(カンマ区切り)';
$lang['minor'] = 'リンクの書き換えを小変更扱いにする。小変更にすると RSS 配信・メール更新通知には表示されない。';
$lang['autoskip'] = '名前空間移動時のエラーの自動スキップ。デフォルトは有効。';
$lang['autorewrite'] = '名前空間移動後のリンクの自動書き換え。デフォルトは有効。';
$lang['pagetools_integration'] = '名称変更ボタンのページツールへの追加';
+3
View File
@@ -0,0 +1,3 @@
====== 移動管理 =====
この画面では、Wiki 内の名前空間・ページ・メディアファイルをドラッグ&ドロップで再配置することができます。
+67
View File
@@ -0,0 +1,67 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Gary Owen
* @author Myeongjin <aranet100@gmail.com>
* @author Jaemin Kim <cooremna@gmail.com>
*/
$lang['menu'] = '문서와 이름공간 이동';
$lang['inprogress'] = '(이동 보류 중)';
$lang['treelink'] = '다른 방법으로 이 간단한 양식은 <a href="%s">트리 기반의 이동 관리자</a>를 사용하여 위키의 복잡한 구조 조정을 관리할 수 있습니다.';
$lang['notexist'] = '%s 문서가 존재하지 않습니다';
$lang['norights'] = '%s 문서를 편집할 충분하지 않은 권한이 있습니다.';
$lang['filelocked'] = '%s 문서가 잠겨 있습니다. 나중에 다시 시도해주세요.';
$lang['notchanged'] = '%s 문서에 주어진 새 대상이 없습니다. (위치가 바뀌지 않음)';
$lang['exists'] = '%s 문서는 %s 문서로 이동할 수 없으며, 대상이 이미 존재합니다.';
$lang['notargetperms'] = '%s 문서를 만들 권한이 없습니다.';
$lang['medianotexist'] = '%s 미디어 파일이 존재하지 않습니다';
$lang['nomediarights'] = '%s 문서를 삭제할 충분하지 않은 권한이 있습니다.';
$lang['medianotchanged'] = '%s 문서에 주어진 새 대상이 없습니다. (위치가 바뀌지 않음)';
$lang['mediaexists'] = '%s 미디어는 %s 미디어로 이동할 수 없으며, 대상이 이미 존재합니다.';
$lang['nomediatargetperms'] = '%s 미디어 파일을 만들 권한이 없습니다.';
$lang['indexerror'] = '%s 검색 색인을 업데이트하는 동안 오류';
$lang['metamoveerror'] = '%s 문서의 메타 파일을 이동할 수 없습니다';
$lang['atticmoveerror'] = '%s 문서의 첨부 파일을 이동할 수 없습니다. 수동으로 이동해주시기 바랍니다.';
$lang['mediametamoveerror'] = '%s 미디어 파일의 메타 파일을 이동할 수 없습니다';
$lang['mediamoveerror'] = '%s 미디어 파일을 이동하는 데 실패했습니다';
$lang['mediaatticmoveerror'] = '%s 문서의 첨부 파일을 이동할 수 없습니다. 수동으로 이동해주시기 바랍니다.';
$lang['renamed'] = '문서 이름이 %s에서 %s(으)로 바뀌었습니다';
$lang['moved'] = '문서가 %s에서 %s(으)로 이동되었습니다';
$lang['move_rename'] = '문서가 %s에서 %s(으)로 이동되고 이름이 바뀌었습니다';
$lang['delete'] = 'move 플러그인에 의해 삭제됨';
$lang['linkchange'] = '링크가 이동 작업으로 인해 적응했습니다';
$lang['intro'] = '이동 작업은 아직 시작되지 않았습니다!';
$lang['preview'] = '실행할 바뀜을 미리 봅니다.';
$lang['inexecution'] = '이전 이동이 완료되지 않았습니다 - 실행을 계속하거나 중단하려면 아래 버튼을 사용하세요.';
$lang['btn_start'] = '시작';
$lang['btn_continue'] = '계속';
$lang['btn_retry'] = '항목 다시 시도';
$lang['btn_skip'] = '항목 건너뛰기';
$lang['btn_abort'] = '중단';
$lang['legend'] = '현재 문서 또는 이름공간 이동';
$lang['movepage'] = '문서 이동';
$lang['movens'] = '이름공간 이동';
$lang['dst'] = '새 이름:';
$lang['content_to_move'] = '이동할 내용:';
$lang['autoskip'] = '오류를 무시하고 이동할 수 없는 문서나 파일을 건너뛰기';
$lang['autorewrite'] = '이동을 완료하고 나서 링크를 올바르게 다시 쓰기';
$lang['move_pages'] = '문서';
$lang['move_media'] = '미디어 파일';
$lang['move_media_and_pages'] = '문서와 미디어 파일';
$lang['nodst'] = '주어진 새 이름이 없습니다';
$lang['noaction'] = '정의한 이동이 없습니다';
$lang['renamepage'] = '문서 이름 바꾸기';
$lang['cantrename'] = '문서는 지금 바로 이름을 바꿀 수 없습니다. 나중에 시도해주시기 바랍니다.';
$lang['js']['rename'] = '이름 바꾸기';
$lang['js']['cancel'] = '취소';
$lang['js']['newname'] = '새 이름:';
$lang['js']['inprogress'] = '문서의 이름을 바꾸고 링크를 조절하는 중...';
$lang['js']['complete'] = '이동 작업이 완료되었습니다.';
$lang['js']['renameitem'] = '이 항목 이름 바꾸기';
$lang['js']['add'] = '새 이름공간 만들기';
$lang['js']['duplicate'] = '죄송하지만, "%s" 문서는 이미 이 이름공간에 존재합니다.';
$lang['root'] = '[루트 이름공간]';
$lang['noscript'] = '이 기능은 자바스크립트가 필요합니다';
$lang['moveinprogress'] = '현재 진행 중인 다른 이동 작업이 있으므로, 지금 바로 이 도구를 사용할 수 없습니다.';
+10
View File
@@ -0,0 +1,10 @@
====== 이동 ======
이 플러그인은 다음 제한 안에서 현재 문서를 이동하고/거나 이름을 바꾸거나 현재 이름공간을 이동하고/거나 이름을 바꿀 수 있습니다:
* 현재 이름공간에서 현재 문서/모든 문서에 대한 편집 권한이 있어야 합니다.
* 이동되는 문서는 편집을 위해 잠겨 있지 않아야 합니다.
* 문서 이동을 위해서는 대상 이름공간에서 만들기 권한도 필요합니다.
* 같은 이름으로 된 문서가 이미 존재하는 이름공간으로 문서를 이동할 수 없습니다.
기존에서 새로 이동하는 문서의 모든 링크는 새 위치와/나 이름을 반영하도록 바뀝니다.
+3
View File
@@ -0,0 +1,3 @@
====== 진행 중인 이동... ======
이동을 진행하는 동안 이 문서를 열어두시기 바랍니다.
+13
View File
@@ -0,0 +1,13 @@
<?php
/**
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*
* @author Myeongjin <aranet100@gmail.com>
* @author Jaemin Kim <cooremna@gmail.com>
*/
$lang['allowrename'] = '문서의 이름을 바꿀 수 있는 그룹 및 사용자. (쉼표로 구분)';
$lang['minor'] = '링크 조절을 사소한 바뀜으로 표시하겠습니까? 사소한 바뀜은 RSS 피드와 구독 메일에 나열되지 않을 것입니다.';
$lang['autoskip'] = '기본적으로 이름공간 이동에서 오류를 자동으로 건너뛰도록 활성화합니다.';
$lang['autorewrite'] = '기본적으로 이름공간을 이동하고 나서 자동으로 링크 다시 쓰기를 활성화합니다.';
$lang['pagetools_integration'] = '페이지도구에 이름 새로짓기 버튼 추가하기';
+3
View File
@@ -0,0 +1,3 @@
====== 이동 관리자 =====
이 인터페이스는 드래그 앤 드롭을 통해 위키의 이름공간, 문서와 미디어 파일을 재배열할 수 있습니다.

Some files were not shown because too many files have changed in this diff Show More