MySkin: select, create and edit your favorite stylesheet
Theme support available in 1.2!
This page refers to beta functionality supported until Wikka 1.1.x. As of version 1.2 Wikka introduces support for 100%-modular themes: check this page for more information or this tutorial to learn how to design custom themes.Following the suggestions of JsnX and JavaWoman, and using code I had written for the WikkaSkinEditor action, I've created a new action that allows registered users to create their own custom skin and modify it to their taste. Feel free to test it and give your feedback.
Current version: 2.2
2.2
- Added JW's patches
2.1
- variables are initialized;
- added a bunch of system-configurable options;
- renamed user skins to user_username.css;
- skin storage: cookies for non registered users / sessions for registered users;
- added titles to form elements;
- added "Hide source" button, as per NilsLindenberg's suggestion;
- renamed "my skin" as "custom skin", as per JavaWoman's suggestion;
To do
- store user skins in DB;
How to use it
After installing the code (see below), just add to one of your pages {{myskin}} and start playing
How to install it
1. Create the action (actions/myskin.php)
- <?php
- /**
- * Allows users to select alternate skins and to edit their custom skins.
- *
- * This action allows the user to select a skin among those available in
- * the Wikka css folder. A form allows to display the markup of each skin.
- * Registered user can create it and modify their own custom skin. The
- * first creation of a custom user skin consists in the generation of a new
- * css stylesheet containing the default wikka CSS settings (as specified
- * in the Wikka config file) and stored with the name of the user. Once a
- * custom user skin exists, the owner of the skin can modify it, overwrite
- * it with an existing skin, or restore the default settings. Wikka
- * administrators have write access to all the skins.
- *
- * Cookies must be enabled for the selector to work and the css folder must
- * be write-accessible to the script in order to read, edit and save skins.
- *
- * @package Actions
- * @name MySkin
- *
- * @author {@link http://wikka.jsnx.com/DarTar DarTar}
- * @version 2.2
- * @since Wikka 1.1.X
- *
- * @output displays a form for selecting alternate skins and edit
- * custom user skins.
- * @todo -integrate with UserSettings.
- */
- // get skin names
- $defaultskin = $this->config['stylesheet'];
- $currentskin = (!$this->GetCookie('wikiskin')) ? $defaultskin : $this->GetCookie('wikiskin'); # JW 2005-07-08 FIX possibly undefined cookie
- $postedskin = $_POST["skin"];
- // build form chunks
- $setskin = '<input type="submit" name="action" value="Set skin" />';
- $showsource = '<input type="submit" name="action" value="Show source" />';
- $hidesource = '<input type="submit" name="action" value="Hide source" />';
- $editsource = '<input type="submit" name="action" value="Edit source" />';
- $savesource = '<input type="submit" name="action" value="Save modified source" />';
- $createskin = '<input type="submit" name="action" value="Create my skin" />';
- $importskin = '<input type="submit" name="action" value="Save current skin as my skin" />';
- $restoreskin = '<input type="submit" name="action" value="Restore to default settings" />';
- // functions
- function WriteSkin($file, $content){
- }
- function ReadSkin($file){
- return $css_content;
- }
- echo $this->Format("=== Select a Wikka skin: === --- ");
- switch ($_POST["action"]) {
- case "Save modified source":
- // saves modified skin to file
- WriteSkin($currentskin, $_POST["mod_css_content"]);
- // no break - skin is automatically updated
- case "Set skin":
- // change current skin and reload page
- // begin change by AlexRust - May 28 2009
- //$this->SetPersistentCookie("wikiskin", $postedskin);
- $this->SetSkin($postedskin);
- // end change by AlexRust - May 28 2009
- $this->Redirect($this->href());
- break;
- case "Save current skin as my skin":
- // import and save current skin as user skin
- $css_content = ReadSkin($currentskin);
- WriteSkin($myskin, $css_content);
- $this->SetPersistentCookie("wikiskin", $myskin);
- $this->Redirect($this->href());
- }
- break;
- case "Create my skin":
- // first time user skin creation
- $css_content = ReadSkin($defaultskin);
- WriteSkin($myskin, $css_content);
- $this->SetPersistentCookie("wikiskin", $myskin);
- $this->Redirect($this->href());
- }
- break;
- case "Restore to default settings":
- // restore user skin to default settings
- $css_content = ReadSkin($defaultskin);
- WriteSkin($myskin, $css_content);
- $this->SetPersistentCookie("wikiskin", $myskin);
- $this->Redirect($this->href());
- }
- break;
- case "Show source":
- // open a readonly textarea with skin source
- $css_contents = ReadSkin($currentskin);
- $showskin = '<textarea id="skinedit" name="display_css_content" cols="80" rows="15" readonly="readonly">'.$css_contents.'</textarea><br />';
- $submit = $hidesource;
- break;
- case "Edit source":
- // open an editable textarea with skin source
- $css_contents = ReadSkin($currentskin);
- $showskin = '<textarea id="skinedit" name="mod_css_content" cols="80" rows="15">'.$css_contents.'</textarea><br />';
- $submit = $savesource;
- break;
- }
- // retrieve skin list
- $skinlist = '<select name="skin">';
- // put on top of the list the default and custom skin
- $defaultselected = ($defaultskin == $currentskin)? " selected=\"selected\"" : "";
- $myselected = ($myskin == $currentskin)? " selected=\"selected\"" : "";
- $skinlist .= '<option value="'.$defaultskin.'"'.$defaultselected.'>(Default skin: '.$defaultskin.')</option>';
- if ($this->GetUser() && file_exists("css/".$myskin)) $skinlist .= '<option value="'.$myskin.'"'.$myselected.'>(My skin: '.$myskin.')</option>';
- // get other skins
- $noskinmask = '^('.$defaultskin.'|'.$myskin.'|xml.css|print.css|\.(.*))$';
- $selected = ($file == $currentskin)? " selected=\"selected\"" : "";
- $skinlist .= '<option value="'.$file.'"'.$selected.'>'.$file.'</option>';
- }
- }
- $skinlist .= '</select>';
- // give write access to the skin owner and to admins
- $submit = ($this->IsAdmin() || $currentskin == $myskin)? $editsource : $showsource;
- }
- // create form
- print $this->FormOpen("","","post");
- print $skinlist.$setskin."<br /><br />".$showskin.$submit."<br /><br />\n";
- // show user skin options
- if ($this->GetUser()) {
- $mysubmit = $createskin;
- } else {
- $myskinname = "(".$myskin.")";
- $mysubmit = ($currentskin == $myskin)? $restoreskin : $importskin.$restoreskin;
- }
- print $this->Format(" ---- === My skin ".$myskinname." === --- ");
- print $mysubmit;
- }
- // close form
- print $this->FormClose();
- ?>
2. Modify the wikka core (wikka.php)
Add the following code in ./wikka.php immediately after the //COOKIES section.
Note: This section has moved to ./libs/Wakka.class.php, and the following can be placed after the GetCookie($name) function.
Updated 5/5/2009 by PezHore: Corrected the reference of cookie 'skin' to 'wikiskin', and changed the cookie retrieval from $skin = $_COOKIE['wikiskin] to use GetCookie function. Also removed the duplicate functions
// SKINS
function GetSkin()
{
if ($this->GetUser())
{
$skin = $_SESSION['wikiskin'];
} else
{
if ($_COOKIE['wikiskin'])
{
$skin = $this->GetCookie('wikiskin');
} else
{
$skin = $this->GetConfigValue("stylesheet");
}
}
return $skin;
}
function SetSkin($skin)
{
if ($this->GetUser())
{
$_SESSION['wikiskin'] = $skin;
} else
{
$this->SetPersistentCookie('wikiskin', $skin);
}
}
function GetSkin()
{
if ($this->GetUser())
{
$skin = $_SESSION['wikiskin'];
} else
{
if ($_COOKIE['wikiskin'])
{
$skin = $this->GetCookie('wikiskin');
} else
{
$skin = $this->GetConfigValue("stylesheet");
}
}
return $skin;
}
function SetSkin($skin)
{
if ($this->GetUser())
{
$_SESSION['wikiskin'] = $skin;
} else
{
$this->SetPersistentCookie('wikiskin', $skin);
}
}
3. Modify the Wikka Header (actions/header.php)
To allow skin selection a small modification of the header is needed:
original actions/header.php
<link rel="stylesheet" type="text/css" href="css/<?php echo $this->GetConfigValue("stylesheet") ?>" />
modified actions/header.php
<link rel="stylesheet" type="text/css" href="css/<?php echo $this->GetSkin() ?>" media="screen" />
4. Add the following system options
original wikka.config.php
"stylesheet" => "wikka.css",
modified wikka.config.php
"stylesheet" => "wikka.css",
"allow_select_skin" => "1",
"display_custom_skins" => "1",
"allow_create_custom_skin" => "1",
"allow_display_skin_source" => "1",
"allow_select_skin" => "1",
"display_custom_skins" => "1",
"allow_create_custom_skin" => "1",
"allow_display_skin_source" => "1",
Understanding the system options
- stylesheet
Defines the system stylesheet;
- allow_select_skin
Allows users to switch stilesheet;
- display_custom_skins
Displays custom skins in the list of selectable stylesheets;
- allow_create_custom_skin
Allows registered users to create custom skins;
- allow_display_skin_source
Allows users to display (and edit) the source of a skin;
CategoryUserContributions CategoryLayout
What exactly is the status of this page / code?
I'm asking because I ran into a bug with the beta code as present on this site (actually caused by the GetCookie() method but turning up as a problem with skins), and fixed it - this involves (mostly small) changes to:
wikka.php (GetCookie() method)
actions/editskin.php
actions/header.php
actions/myskin.php
actions/selectskin.php
actions/skin.php
I am not sure whether code on this page needs to be changed accordingly.
In case the session variable doesn't exist, it will also have to default to the config setting.
Possibly superfluous explanation:
if ($somevar) assumes $somevar exists and you can evaluate its value as a boolean.
if (isset($somevar)) evaluates whether $somevar exists - which one needs to verify (or be absolutely certain of) before evaluating something that may not exist.
But when changing the default_stylesheet in wikka.config.php from the CPANEL in my shared server and then running the site, I get different skin from each of IE,OPERA and FF browsers on my computer, (in all the cases I am not being logged in - viewing site as a visitor) I don't get it ?
<link rel="stylesheet" type="text/css" href="css/" media="screen" />
- Rich S
- you have a line for "stylesheet" in wikka.config.php (it was called "default_stilesheet" in version 2.1)
- the value for "stylesheet" is the name of an existing stylesheet in your css/ folder which the server can access.
Once you've checked these points, please tell me whether you are having this issue as a logged-in or anonymous user (in case you are logged-in, make sure your browser is set to accept cookies).
It looked to me as if most of the code was relying on setting a cookie but the GetSkin() function was actually accessing the $_SESSION var instead of the cookies. My quick fix was to add
$_SESSION['wikiskin'] = $postedskin;
after line 74 of myskin.php.
Please note that this is the 1st time ever i've looked at PHP
(though I've been developing software for far too long :-)
)
It is quite possible I've missed something obvious. It would be great if someone could help me out. Cheers, Nick Damoulakis
Is that correct?
Cheers, Nick Damoulakis
Thanks for pointing this out. I'll try to fix the above issues (which seem to be reported by several users) asap.
1)Set skin button does not seem to actually change the skin!!
I am running two Wikka's on my server. (A and B lets say)
On A I am not able to change skins but on B it could be done
but now any skin I change on the B installation is reflected on the A.
I don't think its a matter of the installations being on the same server but ruther the fact that both look for the same cookie in my PC.
For more info look on WikkaBugs.
For the time being (waiting for an actual "CSS release") you might want to take a look at this unofficial development package, that issues a (woking) skin editor/selector based on the new template:
http://dartar.free.fr/code/
I was wondering if you create cookies with something unique in them so it would be different in each install, I am looking at something like this, but I am still new to the code and I am not sure how to implement it yet.
In any case, the fault appeared to always be with setting/getting session info.
I finaly clicked and looked at my PHP INI file, which had a line in it specifying the sessions dir as './session', which doesn't work. It looks like relative paths are not supported, so I changed it to 'H:/PHP5/sessions' and all is now well.
I hope this may help anyone else tripping over this.
btw, I used the SKIN.PHP file from the 1.1.6dev version with the appropriate mods in WIKKA.PHP.
Running this on a test site http://mbev.net/melissa
My main site http://mbev.net/wikka (I love the Wikka Wakka Wiki software - THANKS)
I tried setting every occurance of "skin" to "wikiskin" (shown in red under step 2) and tried setting every combination of changing only some of them.
Sorry for being so ignorant about coding... see http://mbev.net/melissa/MikeBevington
Cheers,
Nick
=====
It looked to me as if most of the code was relying on setting a cookie but the GetSkin() function was actually accessing the $_SESSION var instead of the cookies. My quick fix was to add
$_SESSION['wikiskin'] = $postedskin;
after line 74 of myskin.php.
=====
If your sessions have been working up to this point, I doubt it's a php.ini config issue...
wget -r -l1 -nd --no-parent -A.css http://wikkawiki.org/css/
Maybe a nightly tarball of .css files might be a more bandwidth-friendly alternative...
Also, I would suggest adding the following to about line 140 of myskin.php to ensure that only .css files are make available in the skins dropdown box:
if (!preg_match('/'.$noskinmask.'/', $file) &&
preg_match('/^.*\.css$/', $file)) {
(There's probably a more graceful way to do this with only one regexp, but I didn't spend a lot of time on this.)
And change this:
if ($this->GetUser())
{
//$skin = $_SESSION['wikiskin'];
$skin = $_COOKIE['wikiskin'];
}
-- fatcop
Stable? It is always a good idea to backup your tables :) I am not sure if the last open issue with users creating their own skin was resolved so perhaps it is better to disable this for the moment?
(like: expression, moz-binding, content, behavior, include-source,..)
thanks a lot for the great contribution!!
One thing: Are the system options are already evaluated? I want my users to be able to select a skin but not change anything. I set all options except "allow_select_skin" to 0 but it seems to have no effect. I can't find any reference to those options in the source code.
I helped myself and commented out the write function of myskin.php, but this is a pretty "dumb" workaround.
Any hints?
I cannot test it right now. But maybe in section 3 of the modification there has to be a semi-colon right before '?>'. Section 2 looks correct. I cannot test section 1 right here.
Please let me know if I am in the right files and/or what I should do to complete steps 3 & 4. My objective is to create a custom skin so the wiki pages have a simialr look and feel to my HTML pages. "thank you" in advance for your time and help.