This page gives examples or mini-applications of WikiSh in action...
Note that examples surrounded by {( ... )} are meant to be placed in the body of a page (even if they are formatted here as multiple lines MXes must always be put on a single line). Examples without these brackets are meant to be run from the control panel. The control panel allows you to format your commands on multiple lines and is thus much easier to work with.
Redirect to a given page via a button (see ButonLink)
- Going to the pmwiki homepage
{(wikish_form quickform process)}
(:input submit name=gohome value="Go To Pmwiki Homepage":)
{(wikish if test -n ${gohome}; then; wikish_form redirect target=pmwiki/pmwiki; fi)}
- Redirecting to a given action on the current page via a button (see 2nd example at ButonLink)
- Note that the final set of 3
{(wikish ...)} MXes could have been put in a single section with (wikish source) and then formatted in multiple lines for readability. Or they could have been put all in a single MX on a single line {(wikish if ... fi; if ... fi; if ... fi)}
{(wikish_form quickform process)}
(:input submit button "Projects" value="Projects":)
(:input submit button "Products" value="Products":)
(:input submit button "PO" value="PO":)
{(wikish if test ${button} == "Projects"; then; wikish_form redirect target={$FullName}?action=proj; fi)}
{(wikish if test ${button} == "Products"; then; wikish_form redirect target={$FullName}?action=products; fi)}
{(wikish if test ${button} == "PO"; then; wikish_form redirect target={$FullName}?action=PO; fi)}
(:if equal {$action} Projects:)
handle projects here
(:if equal {$action} Products:)
handle products here
(:if equal {$action} PO:)
handle PO here
(:ifend:)
- I have followed the 2nd example from ButonLink fairly slavishly above. Going a little "bigger picture" it might be better not to use the redirection and at all but rather use the button name directly without the redirect (i.e., get rid of the final 3
{(wikish ...)} lines completely). If you did this the code would look like this:
{(wikish_form quickform process)}
(:input submit button "Projects" value="Projects":)
(:input submit button "Products" value="Products":)
(:input submit button "PO" value="PO":)
(:if equal ${button} Projects:)
handle projects here
(:if equal ${button} Products:)
handle products here
(:if equal ${button} PO:)
handle PO here
(:ifend:)
- EXPLANATION
- The
{(wikish_form ... process)} loads all $_GET variables into WikiSh variables which are then available via the ${var} syntax. (A similar approach could be taken using the httpvariables recipe, I believe, and ProcessForm does the same sort of thing with Page Vars.) This is really the only contribution of WikiSh to this particular solution -- everything else is core stuff...
- The
{(wikish_form quickform ...)} is simply a shorthand for the setting up of the form establishment of the hidden fields for pagename, etc. In other words, pure, unadulterated laziness... :-)
Allow a given user to log in and automatically be taken to the appropriate home page
- This script does NOT need any write permissions.
- Assumptions:
- All pages in Client.* group are homepages with an appropriate and unique read password set for each page
- Creation of a new client homepage is simply a question of creating the new page in the Client group and setting a unique read password
- The following text will be placed in a separate page in a separate group (Login.Login or Welcome.Login or something) which will be the main login page for anyone wanting to go to their homepage (this is the link you would give to your client, for instance):
{(wikish set -s LIST = normal; for i in Client.*; do; if test -r ${i}; then; wikish_form redirect target=${i}; exit; fi; done; (JOIN THIS LINE)
wikish_form redirect target={$FullName}?action=login)}
- Note that the text (JOIN THIS LINE) should be deleted along with the newline - the entire MX should be on a single line
- Note that it should all be on a single line as that is a current restriction on markup expressions
- The above is all you need, but if you want to see this in a more readable form, it could be run putting the following functionally identical source on the page (basically it puts the above script in a multi-line "pretty" format and then "calls" it via
{(wikish source ...)} ):
{(wikish source {$FullName}#GotoClient)}
(:if false:)
[[#GotoClient]]
set -s LIST = normal
for i in Client.*
do
if test -r ${i}
then
wikish_form redirect target=${i}
exit
fi
done
wikish_form redirect target={$FullName}?action=login
[[#EndGotoClient]]
(:ifend:)
- EXPLANATION (see comments in the code below)
set -s LIST = normal # Make sure the Client.* doesn't include RecentChanges, other system pages
for i in Client.* # Loop through every page in the Client group
do
if test -r ${i} # If the current Client.X page is readable...
then
wikish_form redirect target=${i} # Redirect to it
exit # and stop processing this script
fi
done
# If I got here then there are NO pages which are readable -- present a login form to allow the
# user to enter another password
wikish_form redirect target={$FullName}?action=login
- Caveats
- There may be better "big-picture" solutions using authuser and the user ID, but the requested functionality used the password-only security model. As far as I can see this solution would also work with the authuser security model.
Sum up many PTVs named var1, var2, var3, ..., var30
- This script does NOT need any write permissions.
- It is assumed that the variable are already assigned on the current page in this form:
(:var1:23:)
- The current page is assumed to be named Sum -- if you name it something else then you will need to change the "wikish source Sum#totalit" to use your pagename.
- The #totalit section could be placed on a different page - for simplicity I've placed it all on the same page. Just copy/paste this code into your page with your PTVs and you should get a total.
{earlymx(wikish source Sum#totalit)}
And here is the official total: {$total}
(:if false:)
[[#totalit]]
set i = 1
set --pv total = 0
while test ${i} -le 30
do
set --pv total += {$:var${i}}
echo "running total ${i} = $total\\\n"
set i ++
done
echo total = $total
[[#totalitend]]
(:if:)
- EXPLANATION
- The
{earlymx(...)} form is necessary because you are setting a PV ({$total}) and want to be able to use it. Normally MXes are processed *after* variables are processed. The earlymx form does the same MX processing, but it places the MX markup rule earlier in the process so PVs created during the WikiSh script will be available in the text of your page.
- The
--pv option to set indicates that a PV should be created rather than a normal WikiSh variable.
- Note the use of a dynamically-named variable with the
{$:var${i}} syntax. Since characters like a dollar sign and curly braces are illegal in a PTV name you are guaranteed that the ${i} will be substituted first (the order of the rules of markup and the way WikiSh does WikiSh variables ensures this as well). This leaves an unseen intermediate form that looks like {$:var1} (or another number) which then gets substituted in turn.
- In the "
echo total = $total" you see that $total is used instead of $total. This is because within WikiSh code you have to treat PVs as if you were inside a (:pagelist ...:) -- otherwise they will be prematurely substituted.
Create test data for the Summing Variables example above.
- This script requires write privilege on the current page (assuming WikiSh.Sum)
- This script is identical to that above except it is what was used for testing. To that end the test data can be created by pushing the "Make List" button - it will create 30 PTV assignments on the current page immediately below the
(:comment BELOWTHIS:). Then if you want to sum the values then you press the "Sum Them" button.
- This example is given as one option of how testing could occur during development of a WikiSh recipe.
{earlymx(wikish_button A "Sum Them")(wikish source Sum#totalit)}
{earlymx(wikish_button B "Make List")(wikish source Sum#makevars)}
(:comment BELOWTHIS:)
And here is the official total: {$total}
(:if false:)
[[#makevars]]
set RANDOM_MAX = 10
set RANDOM_MIN = 0
set i = 1
while test ${i} -le 30
do
echo "(:var${i}:${RANDOM}:)" >WikiSh.Sum>BELOWTHIS
set i ++
done
[[#makevarsend]]
[[#totalit]]
set i = 1
set --pv total = 0
while test ${i} -le 30
do
set --pv total += {$:var${i}}
echo "running total ${i} = $total\\\n"
set i ++
done
echo total = $total
[[#totalitend]]
(:if:)
====
DEBUG
(:messages:)
- EXPLANATION
- Observe the setting of RANDOM_MAX and RANDOM_MIN and then the use of
${RANDOM} to get random integers.
- Note the redirection (outputspec) in this form:
- >Sum>BELOWTHIS
- This sends the output of the "echo" command onto the page named Sum (in the current group) and places it on the line immediately after the first line matching the pattern BELOWTHIS.
- Since each iteration will put the data immediately below that line and we start with var1 that means that the data will end up being in reverse order. You could solve this "problem" either by using
>Sum<ABOVETHIS to put the data immediately above the line matching that pattern (obviously you would need to change the comment to match) or, alternatively, you could start with i as 30 and decrement instead of increment down to 1. Since they are invisible it didn't make any difference in this case and so the example leaves them in reverse order.
- For other explanation see the previous example.
Make a VERY rough shopping cart (can be beautified fairly trivially)
- Requires write permission to the Order and Form pages within the group "Shop" (as I've got it here)
- Here is what gets placed in Shop.Items (item#:description:price):
- Presumably this very simple data definition would need to be expanded with more fields, etc.
001:Chair:17.89
002:Table:79.23
003:Rug:50.01
004:Door:129.01
- Here is what gets placed in Shop.Code:
- Making tables for the form in Shop.Code#genform and the order page in Shop.Code#ValidateForm is pretty trivial and would make it look a lot nicer...
{(wikish_button a "Generate Form")(wikish source {$FullName}#genform)}
(:if false:)
[[#ValidateForm]]
if test ${Checkout} != "Checkout"
then
exit
fi
set nogood = 0
set totalprice = 0
set -s orderpage = Shop.Order
echo "(:linebreaks:)" >${orderpage}
while read --IFS:: ItemNo ItemName ItemCost <Items
do
if ! test ${Item${ItemNo}} ~= "/^\d*$/"
then
echo "ERROR: Item Number ${ItemNo} had a non-numeric quantity." >>${orderpage}
set nogood = 1
else
if test -z ${Item${ItemNo}}
then
set Item${ItemNo} = 0
fi
if test ${Item${ItemNo}} -gt 0
then
set extcost = ${Item${ItemNo}} * ${ItemCost}
set totalprice += ${extcost}
echo "${Item${ItemNo}} items of ${ItemName} (item number ${ItemNo}): ${extcost}" >>${orderpage}
fi
fi
done
if test ${nogood} -eq 1
then
echo "Error invalid. Please fix errors."
else
echo "Total Price for entire order: ${totalprice}" >>${orderpage}
wikish_form target=${orderpage} REDIRECT
fi
[[#endValidateForm]]
[[#genform]]
set -s formpage = Form
set -s openparen = '('
set -s closeparen = ')'
echo "{(wikish_form QUICKFORM PROCESS)}" >${formpage}
while read --IFS:: ItemNo ItemName ItemCost <Items
do
echo "${ItemName}: (:input text name=Item${ItemNo}:)\\" >>${formpage}
done
echo "${openparen}:input submit Checkout Checkout:${closeparen}" >>${formpage}
# (the following 2 lines should be combined into 1
echo "${openparen}:if false:${closeparen}\n{${openparen}wikish source
Code#ValidateForm${closeparen}}\n${openparen}:if:${closeparen}" >>${formpage}
[[#genformend]]
(:if:)
- FUNCTIONALITY: When you browse the Shop.Code page you will have a button labeled "Generate Form". Push that and it will create the form in Shop.Form. Navigate to that page and you will be able to enter quantities for each item and press "Checkout" which will create a very rough "Order" page (with line items, extended prices, total, etc.) and redirect you to that page.
Make a "static" pagelist, doing selection by title by regular expression
- Requires write permission on the "Foo" file (or whatever you choose for output)
- Requires multiple invocations due to PHP timeouts
- A straight
(:pagelist ...:) is superior in every way to this solution with these exceptions:
- If you have more pages than can be processed in a single 30-second time period then you have no other options with a normal
(:pagelist ...:)
- The static pagelist is going to be much quicker while browsing (after it is set up) as compared to a normal pagelist that must be recreated from scratch each time.
- This script will create a STATIC pagelist. That means you will need to regenerate it if a title is changed or if a page is added or deleted. It has its uses (esp speed) but it is not the same as a pagelist.
- Technical Notes:
- Note usage of REFPAGE (set to a pagename) which causes all PVs following (
{$Title} in our example) to be evaluated from that page's context
- Note that
${titlevar} had to be set in 2 steps. If the text "{$Title}" appeared verbatim in the text of the program then PmWiki would have evaluated it before we ever used it. Then ${titlevar} would have held the value of the title of the current page ("Control Panel") rather than the name of the variable ("{$Title}"). Doing it in 2 separate steps means that the text "{$Title}" never occurs in the text of the script so it will not be evaluated prematurely.
- The pages with a title which matches the pattern (in this case those that start with A, B, or C) will be written in plain text to the page Foo. There are at least 2 ways to format your list more attractively:
- Examples of "pretty formatting" while writing to Foo
echo ${fn} >>Foo # plain text
echo "||${fn} ||${title} ||" >>Foo # table with pagename and title
echo "[[${fn}|+]]" >>Foo # links with dynamically generated title
echo "[[${fn}|${title}]]" >>Foo # links with static title (fast)
- Or you could take the text in Foo and put it back in a
(:pagelist ...:) to do the formatting for you, but only looking at the pages that match your title criteria:
(:pagelist name={(cat --newline:, Foo)}:)
- Explanation: Setting newline to a comma causes all the lines to be written out comma-separated instead of newline-separated and so since each line contains exactly one pagename it becomes a nice input to a pagelist.
- Even though you are using
(:pagelist ...:) your page selection is still being done statically (is that a word?) and so any adds/deletes/title-changes will NOT be reflected in this pagelist until you regenerate the static list again.
read --restoreset # this will not cause an error if there is nothing to restore
if test -z `read --status`
then
echo "Generating list of files to work off of..."
ls --list:normal >Tmp
fi
set -s output = "Foo" # CHANGE THIS VALUE IF YOU WANT YOUR OUTPUT TO GO TO A DIFFERENT PAGE
set -s titlevar = "{$" # Must build the variable in 2 steps or else other markup rules
set -s titlevar .= "Title}" # will substitute it before we can use it
set -s LIST = normal # don't include pages like RecentChanges, AllRecentChanges, PmWiki.*, etc.
while read fn <Tmp
do
#echo "Processing page ${fn}"
set -s REFPAGE = ${fn}
set -s title = ${titlevar}
if test ${title} ~= '/^[ABC]/'
then
echo "FOUND: ${fn} (${title})"
echo ${fn} >>${output} # CHANGE THIS LINE IF YOU WANT THE OUTPUT IN A DIFFERENT FORMAT
else
echo "NOT FOUND: ${fn} (${title})"
fi
set -s REFPAGE = ""
if test ${SECONDSLEFT} -lt 7 # allow 7 seconds for initial compile time plus time to process next file
then
read --saveset
echo "You will need to reinvoke this script to complete. You have finished" `read --status` "files out of" `read --linecount`
exit
fi
done
echo "COMPLETED! Please find your output in ${output}."
read --clearset # Make sure it's all cleared out for the end
Make a "static" list of pages with titles. This list can then be used for a faster pagelist.
- Requires write permission on the "PageList" file (or whatever you choose for output)
- If you put the "PageList" page in the WikiSh group (WikiSh.PageList) then the default $WikiShWriteList is sufficient.
- If you want to put "PageList" in another group, say Site.PageList, then you would need to have a line like this in your config.php after WikiSh.php is included:
- $WikiShWriteList[] = 'Site.PageList';
- Requires multiple invocations due to PHP timeouts
- Normally a script like this would be copy/pasted into the WikiSh.ControlPanel command field and then the execute button pressed multiple times.
- You could also copy/paste the script into it's own page (for instance, WikiSh.MkPageList) and then on another page (for instance, WikiSh.RunMkPageList) you would have only this markup:
{(wikish_button A "Make Pagelist")(wikish source WikiSh.MkPageList)}
- Then instead of pushing the "execute command" button multiple times you would press the "Make Pagelist" button multiple times until the output indicated that the job was done. (Obviously you will have to wait about 30 seconds between each invocation.)
- TIP: When the output page (PageList) is small this script processes a lot of pages each iteration (70-100 on my system). When the output page gets larger things REALLY slow down. (By around 1300 files my system was only able to process about 11 files per 30-second-timeout.) However, the problem is easily solved manually by periodically (as often as every 2 iterations) cut/pasting the output into a new page somewhere (or an editor or whatever). Then save the PageList page as a blank page and things will move along quickly for 2-3 more invocations. Then simply do it again, saving the new content of PageList after the old content you've already saved. At the end of the whole process copy/paste the whole list back into the PageList page. (If this doesn't make sense it is not strictly necessary, but it might save you an hour or so if you are working on a site with a lot of pages.)
- The script could be modified relatively easily to write the output in "chunks" of 50 or 100 files.
- This script will create a STATIC pagelist. That means you will need to regenerate it if a title is changed or if a page is added or deleted. It has its uses (esp speed) but it is not the same as a pagelist.
- This solution is designed to be used when obtaining a list of all pages by title.
- You could take the text in PageList and put it back in a
(:pagelist ...:) to format the output. (:pagelist ...:) will only have to look at the pages that match your title criteria so speed will be dramatically improved:
Pagelist of titles starting with A
(:pagelist fmt=#title name={(wikish grep -i "^\s*A" WikiSh.PageList | cut --newline:, -d# -f2)}:)
Pagelist of titles starting with B
(:pagelist fmt=#title name={(wikish grep -i "^\s*B" WikiSh.PageList | cut --newline:, -d# -f2)}:)
- Explanation: The "grep ..." command selects only lines which begin with an A. Those lines are passed (or piped) to the "cut ..." command which "cuts" each line into fields, cutting wherever the hash symbol (#) is. It then gives back the 2nd field (the pagename). Setting newline to a comma causes all the lines to be written out comma-separated instead of newline-separated and so since each line contains exactly one pagename it becomes a nice input to a pagelist.
- This script depends on the assumption that you will never have a hash symbol (#) in a title. If you do then you'll need to make some changes here...
- Even though you are using
(:pagelist ...:) your page selection is still being done statically (is that a word?) and so any adds/deletes/title-changes will NOT be reflected in this pagelist until you regenerate the static list again.
- Performance gains are as expected. On a system with around 1500 pages which could barely have searched through all titles within 30 seconds there is an almost instantaneous load of the page listed above listing those starting with A and those starting with B.
- Here is the script that would be placed in WikiSh.MkPageList:
set -s output = "WikiSh.PageList" # CHANGE THIS VALUE IF YOU WANT YOUR OUTPUT TO GO TO A DIFFERENT PAGE
read --restoreset # this will not cause an error if there is nothing to restore
if test -z `read --status`
then
echo "Generating list of files to work off of..."
ls --list:normal >Tmp
echo "--> Static pagelist last updated:" `ftime` >${output}
fi
set -s titlevar = "{$" # Must build the variable in 2 steps or else other markup rules
set -s titlevar .= "Title}" # will substitute it before we can use it
set -s PAGEVAR = 'pre' # In processing ${titlevar} WikiSh variables must be processed BEFORE PVs
while read fn <Tmp
do
#echo "Processing page ${fn}"
set -s REFPAGE = ${fn}
echo "${titlevar}#${fn}" >>${output}
if test ${SECONDSLEFT} -lt 7 # allow 7 seconds for initial compile time plus time to process next file
then
read --saveset
echo "You will need to reinvoke this script to complete. You have finished" `read --status` "files out of" `read --linecount`
exit
fi
done
echo "COMPLETED! Please find your output in ${output}."
read --clearset # Make sure it's all cleared out for the end
Compute a portion of a pagename (A "base" name)
- Suppose you have a set of pages in the form Group.Name-Issue-#. The Group.Name is the name of a "base page" you need to access. Here is how you could "compute" the "base name" (Group.Name) from the pagename (Group.Name-Issue-#)
- (There is a built-in solution to this using the $BaseNamePatterns[] array -- the example below merely shows WikiSh capability. The built-in solution is superior.)
- Note that NO write permissions at all are necessary for WikiSh to carry out these functions - thus safe for non-admins to use
A simple solution, suitable for just displaying the name:
{(sed 's/-Issue-.*$//' - {$Name})}
If you wanted to set a PV to that value you could do it like this:
{earlymx(set -s --pv BASENAME = (sed 's/-Issue-.*$//' - {$Name}))}
the basename is {$BASENAME}
(By using the {earlymx(...)} form the MX gets executed early in the markup processing queue and the result is that you can then use the PV set -- otherwise the PV gets set but you can't use it because variables have already been interpolated by the time it is set.)
Do a global search and replace on a large number of files
- Search & Replace (or any other operation which processes a LOT of files) is normally a very challenging operation within a PHP environment because of the default timeouts. WikiSh has implemented some features within the
{(read ...)} MX to help administrators get around this problem.
- Broad write permissions are required prior to running this script. Thus it should be run on pages accessible only by admins.
- Before you run the main script below you should run this short script to make sure you don't have anything hanging around in your session that will cause problems for you...
- Once you have cleared the session (above) then you can put this script (below) into your control panel, change the sed ... line to reflect your search/replace values, and start pressing execute. (If you want it to output a line for each file processed, whether updated or not, then uncomment the echo command immediately above the sed command -- however, this deemphasizes the output from sed -v if you are looking for that specifically.)
read --restoreset # this will not cause an error if there is nothing to restore
if test -z `read --status`
then
echo "Generating list of files to work off of..."
ls | grep -v RecentChanges >Tmp
fi
while read fn <Tmp
do
if test ${SECONDSLEFT} -lt 7 # allow 7 seconds for initial compile time plus time to process next file
then
read --prev --saveset # prev because main looping read has already gone to next line - must retrace steps
echo "You will need to reinvoke this script to complete. You have finished" `read --status` "files out of" `read --linecount`
exit
fi
#echo "Processing page ${fn}"
sed -vi 's/Pete /Peter /g' ${fn}
done
echo "COMPLETED!"
read --clearset
- You will need to re-invoke this script many times, depending on the size of your site and the speed of your server. Simply press "Execute Command" each time to re-invoke it.
Make a group into a WikiTrail
- NOTE: Write permissions would be needed on MyGroup.TrailIndexPage as well as every page that will become part of WikiTrail
ls MyGroup.* | grep -v 'RecentChanges|AnotherPageToSkip' | while read fn
do
echo "${fn}"
echo "<<|[[TrailIndexPage]]|>>" >${fn}<_TOP
echo "* [[${fn}]]" >>MyGroup.TrailIndexPage
done
Create a list of changes made by a particular author:
- Note that NO write permissions at all are necessary for WikiSh to carry out these functions - thus safe for non-admins to use
If you are searching for "John Smith" specifically
{(grep -F "[[~John Smith]]" *.RecentChanges)}
If you want to put it generically in a Profiles.GroupFooter (this allows for an optional space before each capital letter):
{(wikish grep `sed 's/(.)([A-Z])/$1 ?$2/g' - {$Name}` *.RecentChanges)}
If you want to make the output look nicer and in a different order and etc (courtesy of Hans):
||
||'''recent edits by Hans''' || ||
{(wikish grep -F "[[~Hans]]" Site.AllRecentChanges | sed 's/\* (.*?)\. \. \.\s*(.*?)\s*by(.*?)$/||$1 ||$2 ||/U' | sort -ur)}
Get a list of groups
- Note that NO write permissions at all are necessary for WikiSh to carry out these functions - thus safe for non-admins to use
Option 1 (quick - may miss a group every once in a while if it doesn't have a RecentChanges page)
{(wikish ls *.RecentChanges | sed 's/\.RecentChanges//' | sort -u)}
Option 2 (takes longer but is complete)
{(wikish ls *.* | sed 's/\..*$//' | sort -u)}
Print off a different message if a pagelist returns no pages:
- Note that NO write permissions at all are necessary for WikiSh to carry out these functions - thus safe for non-admins to use
- The wrap=inline option is necessary due to the way pagelist interacts with WikiSh. Other options can be changed as you please.
- The MX pagelist is found in the PowerTools recipe and is necessary for this particular solution.
- The command below must be placed on a single line even though it's formatted here on multiple lines
{(wikish set -s list = (pagelist group=XYZ wrap=inline fmt=#bygroup); if test -z "${list}"; then; echo "No pages found!";
else; echo "${list}"; fi)}
Rename a page fixing all links to it
- Note that broad write permissions are necessary for this example. Normally only admins should have this level of permission.
- put the following MX on a page, make sure permissions allow writing to anybody that might need writing to, and then successively re-load the page watching the progress indicators move by. The reason for the multiple reloads is due to the timeouts PHP has for execution time. If you've got a fast server then you can increase the "FilesPerChunk setting right at the beginning.
- List (ls) all files into LsList, search through those one chunk at a time using grep to find which files link the old group/page and put the results in GrepList, go through GrepList one chunk at a time using sed and search/replace for the old group/page with the new group/page.
- You will need PowerTools version 2008/06/22 or later for this to work
- As long as you have a reasonable number of links to the page being renamed (so you don't have to worry about timeouts) this works fine:
set -s OldGroup = TestA
set -s OldPage = A
set -s NewGroup = TestB
set -s NewPage = B
sed -i 's|${OldGroup}([./]\)?)${OldPage}|${NewGroup}$1${NewPage}|gi' `pagelist link=${OldGroup}.${OldPage} sep=\n`
mv ${OldGroup}.${OldPage} ${NewGroup}.${NewPage}
- If you have a page with a large number of links to it (more than 20 perhaps?) or if your server is particularly slow then you may need to limit the pagelist at the end of the 5th line in some way and process it in multiple steps. For instance, you could limit it by saying
name=[A-F]* the first time, name=[G-M]* the second time and etc.
- Explanation
- The first 4 lines simply define variables to hold the old group & page name and the new group & page name. It could have been done just as easily hardcoding those values in the last 2 lines, but having those values in variables allows the script to "isolate" the regular expression from users who may want to remain distant from that type of complication.
- The 5th line beginning "sed" does the substitution fixing all links. It uses the "s|find|replace|ig" command to do the actual replacement. It uses the pagelist command (in backquotes) to determine which pages need to be altered.
- The 6th line simply renames the page to the new name.
Rename an entire group fixing all links to each page
- If you are renaming an entire group then the following script should work for you (assuming that each individual page within the group has a reasonable number of links to it)
- You will need PowerTools version 2008/06/22 or later for this to work
- Before you run the main script below you should run this short script to make sure you don't have anything hanging around in your session that will cause problems for you...
- Once you have cleared the session (above) then you can put this script (below) into your control panel, change the set -s OldGroup = TestA and set -s NewGroup = TestB lines to reflect the names of your old/new groups, and start pressing execute.
- You may want to play with the timeout of 15 - give it less if you are able to process an entire page in less than that or increase it if you need more time
- You may also want to put a "null --timeout:120" at the very top of the script -- in some servers this will allow you to process for 120 seconds instead of only 30. Be aware, however, that there may be other timeouts which may come into play if you lengthen this PHP execution timeout.
#null --timeout:120
read --restoreset # this will not cause an error if there is nothing to restore
set -s OldGroup = TestA
set -s NewGroup = TestB
if test -z `read --status`
then
echo "Generating list of files to work off of..."
ls ${OldGroup}.* >Tmp
fi
while read fn <Tmp
do
if test ${SECONDSLEFT} -lt 15 # allow 15 seconds for initial compile time plus time to process next page
then
read --prev --saveset # prev because main looping read has already gone to next line - must retrace steps
echo "You will need to reinvoke this script to complete. You have finished" `read --status` "files out of" `read --linecount`
exit
fi
set -s OldPage = ${fn#*.} # calculate just the page part, losing the group
set -s NewPage = ${OldPage}
echo "Updating links ${OldGroup}.${OldPage} to ${NewGroup}.${NewPage} ..."
sed -vi 's|${OldGroup}([./]\)?)${OldPage}|${NewGroup}$1${NewPage}|gi' `pagelist link=${OldGroup}.${OldPage} sep=\n`
mv ${OldGroup}.${OldPage} ${NewGroup}.${NewPage}
echo "Moved page ${OldGroup}.${OldPage} to ${NewGroup}.${NewPage} ... DONE"
done
read --clearset
rm Tmp
echo "Entire Process COMPLETED!"
- You will potentially need to re-invoke this script many times, depending on the size of the group and the speed of your server and the number of links to each page. Simply press "Execute Command" each time to re-invoke it.
Create a set of template pages which you then copy into a new group specified in a form
- Note that you will need write permission on the pages which will be created in the new group - normally permissions like this would belong only to the admin. ALTHOUGH you could give create-only permissions to non-admins by setting $EnableWikiShCreatePage but NOT setting $EnableWikiShOverwritePages. Then the worst that could happen from a security perspective is that a bunch of "junk" files could be created by a malicious user.
Create your templates in some (presumably protected) group. Let's say WikiMaster.Page1 and WikiMaster.Page2. Then on WikiMaster.Admin you would put this markup:
===(snip WikiMaster.Admin)===
{(wikish_form QUICKFORM PROCESS)}
New Group:
(:input text name=GroupName:)\\
(:input submit name=submit value=Create:)
{(wikish source {$FullName}#validate)}
(:if false:)
[[#validate]]
if test -n "${submit}"
then
if ! test -n "${GroupName}"
then
echo "ERROR: Must specify the new group name."
else
if test -f ${GroupName}.Page1 || test -f ${GroupName}.Page2
then
echo "ERROR: ${GroupName} already exists."
else
echo "Creating New Team Page...\\\n\\\n"
cp WikiMaster.Page1 WikiMaster.Page2 ${GroupName}
echo "\\\n\\\n...DONE!"
fi
fi
fi
[[#validateend]]
(:if:)
===(snip)===
If you are going to let other people create the groups then you might want to do some other validations on the group name (no disallowed characters, etc), but this will get you the basic operation and you can fine-tune it from there.