Hello,
I have recently installed MediaWiki 1.22.3 and hope to use it to host some documentation. I like the Vector skin and have been using Common.css to add some local styling. All looks great so far and I am very impressed with Mediawiki.
But I would really like to be able to add a "banner" (or menu etc.) to the top of the site, before any standard elements (or possibly sit behind them). I would also like to have a basic idea on changing a few skin elements perhaps. I have little PHP experience (but some other programming languages) so my difficulties are probably stupid and/or basic.
Following Daniel Friesen's "subskin" tutorial (thanks Daniel!) :
http://blog.redwerks.org/2012/02/28/mediawiki-subskin-tutorial/
My site is now using my own skin "Zed Docs". Or so it seems to be - it is identical to Vector at the moment.
However, I can't seem to figure out how to insert any changes in my skin and have them picked up.
I have taken the very basic PHP skin file I created following the tutorial :
ZedDocs.skin.php :
require_once( dirname( __FILE__ ) . '/../Vector.php' );
class SkinZedDocs extends SkinVector {
var $skinname = 'zeddocs', $stylename = 'zeddocs';
function setupSkinUserCss( OutputPage $out ){ parent::setupSkinUserCss( $out ); $out->addModuleStyles( "skins.zeddocs" ); }
}
and copied much of the rest of the Vector.pnp code below it, changing :
class VectorTemplate extends BaseTemplate { ...
to :
class ZedDocsTemplate extends VectorTemplate { ...
(is this correct?)
Then inside this, the whole of the "execute" function :
public function execute() { ...
But nothing I add or modify inside the "execute" function makes any difference to the page I see e.g. adding anything after :
<div id="mw-page-base" class="noprint"></div>
or anywhere else.
I almost certainly have a fundamental misunderstanding somewhere. No doubt coupled with my lack of PHP experience (I know I should really learn more about it).
What am I doing wrong and what do I need to do?
Many thanks for any help or advice.
Cheers,
On Thu, Mar 6, 2014 at 10:20 AM, Alastair Sherringham < alastair@sherringham.net> wrote:
Hello,
I have recently installed MediaWiki 1.22.3 and hope to use it to host some documentation. I like the Vector skin and have been using Common.css to add some local styling. All looks great so far and I am very impressed with Mediawiki.
But I would really like to be able to add a "banner" (or menu etc.) to the top of the site, before any standard elements (or possibly sit behind them). I would also like to have a basic idea on changing a few skin elements perhaps. I have little PHP experience (but some other programming languages) so my difficulties are probably stupid and/or basic.
Following Daniel Friesen's "subskin" tutorial (thanks Daniel!) :
http://blog.redwerks.org/2012/02/28/mediawiki-subskin-tutorial/
My site is now using my own skin "Zed Docs". Or so it seems to be - it is identical to Vector at the moment.
However, I can't seem to figure out how to insert any changes in my skin and have them picked up.
I have taken the very basic PHP skin file I created following the tutorial :
ZedDocs.skin.php :
require_once( dirname( __FILE__ ) . '/../Vector.php' );
class SkinZedDocs extends SkinVector {
var $skinname = 'zeddocs', $stylename = 'zeddocs'; function setupSkinUserCss( OutputPage $out ){ parent::setupSkinUserCss( $out ); $out->addModuleStyles( "skins.zeddocs" ); }
}
and copied much of the rest of the Vector.pnp code below it, changing :
class VectorTemplate extends BaseTemplate { ...
to :
class ZedDocsTemplate extends VectorTemplate { ...
(is this correct?)
I don't think this step is correct. To accomplish a similar end result to what you're looking for, I did basically the same as you in that I created a subskin based on the Vector skin. I did two things differently to get a header on my new subskin.
1. Following the php code in myskin.skin.php I simply pasted the HTML for my header. 2. I added the CSS to style the header html to screen.css and added a call to screen.css right after the addModuleStyles statement in the PHP above with:
$out->addStyle( 'myskin/css/screen.css', 'screen');
I suspect there's a better way to do this, but for now, it's working for me.
I also had to tweak the CSS to make my header fit correctly on the screen within the framework of the inherited Vector skin styling. I accomplished this using Firebug to play with the layout and then editing the CSS by hand afterward.
Then inside this, the whole of the "execute" function :
public function execute() { ...
But nothing I add or modify inside the "execute" function makes any difference to the page I see e.g. adding anything after :
<div id="mw-page-base" class="noprint"></div>
or anywhere else.
I almost certainly have a fundamental misunderstanding somewhere. No doubt coupled with my lack of PHP experience (I know I should really learn more about it).
What am I doing wrong and what do I need to do?
Many thanks for any help or advice.
Cheers,
-- Alastair Sherringham http://www.sherringham.net
MediaWiki-l mailing list MediaWiki-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
Thanks Bill. That's very helpful. I've removed all the extra code I pasted and just stuck a test "div" at the end.
This didn't work - get a blank page. But I noticed that the "<?php" at the top was unterminated. I terminated it and /then/ added my div - and this outputs!
Daniel's tutorial does not terminate the "<?php" tags - I assume they get automatically terminated by EOF. Maybe they should be terminated explicitly in the tutorial.
Now I need to play with the CSS etc. and see what happens.
Thanks for your help.
On 2014-03-06, 8:55 AM, Alastair Sherringham wrote:
Daniel's tutorial does not terminate the "<?php" tags - I assume they get automatically terminated by EOF. Maybe they should be terminated explicitly in the tutorial.
Yes, ?> tags are not necessary at EOF. In fact the practice of adding ?> before EOF leads to bugs where some forms of file transfer programs insert a newline after the ?> creating whitespace that triggers "Headers already sent" fatal errors when uploaded to a webserver. For this reason it's standard practice in MediaWiki to NEVER use a ?> at the end of a PHP file.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
On 2014-03-06, 7:20 AM, Alastair Sherringham wrote:
But nothing I add or modify inside the "execute" function makes any difference to the page I see e.g. adding anything after :
<div id="mw-page-base" class="noprint"></div>
or anywhere else.
I almost certainly have a fundamental misunderstanding somewhere. No doubt coupled with my lack of PHP experience (I know I should really learn more about it).
What am I doing wrong and what do I need to do?
You got the method of extending the template itself correct, you just missed one tiny part. Add $template = 'ZedDocsTemplate' to the line with $skinname and $stylename. This will tell your skin implementation to use the template class you created instead of continuing to inherit the name of the template that SkinVector gives it.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
On 06/03/14 19:12, Daniel Friesen wrote:
Add $template = 'ZedDocsTemplate' to the line with $skinname and $stylename. This will tell your skin implementation to use the template class you created instead of continuing to inherit the name of the template that SkinVector gives it.
Thanks Daniel. I reset what I did to what it was before and added that variable. Now it seems to work and I can modify the file and see changes in the page.
Now I just need to figure out how to add the banner/menu at the top but "pushing" the rest of the page down slightly (at the moment it just sits "behind" current content).
Thanks again for your help!
On 2014-03-06, 12:01 PM, Alastair Sherringham wrote:
On 06/03/14 19:12, Daniel Friesen wrote:
Add $template = 'ZedDocsTemplate' to the line with $skinname and $stylename. This will tell your skin implementation to use the template class you created instead of continuing to inherit the name of the template that SkinVector gives it.
Thanks Daniel. I reset what I did to what it was before and added that variable. Now it seems to work and I can modify the file and see changes in the page.
Now I just need to figure out how to add the banner/menu at the top but "pushing" the rest of the page down slightly (at the moment it just sits "behind" current content).
That's probably due to the absolute positioning that Vector's css uses. You'll have to add some extra css of your own to tweak the top position of stuff, or add a relative positioned wrapper around vector's normal content to contain the absolute position within a box you can push down.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
That's probably due to the absolute positioning that Vector's css uses. You'll have to add some extra css of your own to tweak the top position of stuff, or add a relative positioned wrapper around vector's normal content to contain the absolute position within a box you can push down.
Yes, I think I need to look at some CSS and re-position.
A quick question - Bill's way of adding a header/banner is just to write some HTML directly after the very minimal PHP code as per your tutorial (i.e. after "class SkinZedDocs extends SkinVector {", terminated). This is a much smaller and simpler file obviously that copying all the template code from Vector.php. If one only wants to add a banner/header to the output, is there any reason to do it the "long" way over the short and sweet way?
Cheers,
Alastair
On 2014-03-07, 1:13 AM, Alastair Sherringham wrote:
That's probably due to the absolute positioning that Vector's css uses. You'll have to add some extra css of your own to tweak the top position of stuff, or add a relative positioned wrapper around vector's normal content to contain the absolute position within a box you can push down.
Yes, I think I need to look at some CSS and re-position.
A quick question - Bill's way of adding a header/banner is just to write some HTML directly after the very minimal PHP code as per your tutorial (i.e. after "class SkinZedDocs extends SkinVector {", terminated). This is a much smaller and simpler file obviously that copying all the template code from Vector.php. If one only wants to add a banner/header to the output, is there any reason to do it the "long" way over the short and sweet way?
Firstly, because I misread the question/technique I'm going to give an answer to a different question, one you didn't ask ;). "What's the advantage of making a subclass of VectorTemplate and just copying all of the execute() method instead of simply copying all of the VectorTemplate and renaming it?" Strictly speaking, since the majority of Vector's html is in the template class' execute method instead of broken up or given some form of insertion points, tweaking that technique to include a template subclass with only a copy of execute in it isn't all that much smaller.
The advantage would be that you're still not 100% copying code and if one of the non-overridden methods is changed you don't have to re-copy anything. The disadvantage would be that those few non-overridden methods aren't considered as "public" as the rest of the skin, so there is a slight possibility that someone may make a modification simultaneously to Vector's execute method in core and one of those non-overridden methods that breaks in your clone of Vector because the non-overridden method depends on the changes to execute() that are not in your skin.
As long as you're only duplicating the template portion and keeping the rest like my tutorial either way you still have the advantage of not duplicating Vector's pile of css. Of course neither is really ideal since in both cases a the majority of Vector's template is being duplicated.
Depending on what you want to add and where you want to add it there is a better trick that can be used. Look around the template for the skin you are extending at it's uses of $this->data['somekey'], $this->html('somekey'), $this->text('somekey'). See if the spot you want to insert your html has one of those and it's the right type (ie: You're not trying to insert raw html in a spot that uses $this->text('somekey').
If you find one instead of copying all of execute you can use a hack where you extend execute(), modify $this->data (which is used by ->html and ->text), then just let the parent skin's normal execute() method run with the modified ->data instead of duplicating it.
function execute() { // Modify $this->data['somekey'] parent::execute(); }
Then you keep all the advantages.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
If you find one instead of copying all of execute you can use a hack where you extend execute(), modify $this->data (which is used by ->html and ->text), then just let the parent skin's normal execute() method run with the modified ->data instead of duplicating it.
function execute() { // Modify $this->data['somekey'] parent::execute(); }
Then you keep all the advantages.
Thanks Daniel. That's all quite interesting, although starting to stretch my PHP and Mediawiki understanding a little (I'm learning a lot ...). I may try and have a play and see what happens. My concern is for maintainability and upgrades working, so doing less is attractive.
Right now, I have a very simple file though - your basic "MySkin.skin.php" file with this at the bottom :
<div id="zeddocs-banner"></div>
This seems to work (I'm overriding some CSS positioning in zeddocs/css/screen.css) and I'm tempted to leave it like that for now. Anyway - it's good to have this sort of knowledge around and I'm definitely less "scared" of touching this stuff now.
Thanks again for your help. If it wasn't for your guide, I'd be lost.
Cheers,
On 2014-03-07, 1:13 AM, Alastair Sherringham wrote:
That's probably due to the absolute positioning that Vector's css uses. You'll have to add some extra css of your own to tweak the top position of stuff, or add a relative positioned wrapper around vector's normal content to contain the absolute position within a box you can push down.
Yes, I think I need to look at some CSS and re-position.
A quick question - Bill's way of adding a header/banner is just to write some HTML directly after the very minimal PHP code as per your tutorial (i.e. after "class SkinZedDocs extends SkinVector {", terminated). This is a much smaller and simpler file obviously that copying all the template code from Vector.php. If one only wants to add a banner/header to the output, is there any reason to do it the "long" way over the short and sweet way?
Now that I think I actually understand what you're asking I'll answer your question.
If I understand it right now, Bill is suggesting that you use:
<?php // ... class SkinFubar extends SkinVector { // ... } ?> <header> My html header code. </header> ...
This idea is over 9000% wrong. You're not actually adding anything to the skin at all. The html is simply being echoed whenever the php file is loaded, which is typically the first time SkinFubar is needed. This happens even if the skin isn't used, just as long as it's autoloaded, and is not present if the skin is used to render multiple pages (like DumpHTML).
In one circumstance this can lead to the "headers have already been sent" fatal error as it's possible that the echoed html is output before we define our HTTP headers. Otherwise, ie: if ob_start() happened to be called and collected that text, what happens is this supposed header is really garbage (the technical jargon type) that gets output before any of the skin's html is output.
Which really means that your "header" looks about like this:
<header> My html header code. </header> ... <!DOCTYPE html> <html ...> ...
This html is completely invalid. The entire page <head> is now part of an implicitly inserted empty <body>, any class defined on <html> or <body> probably won't even target the DOM in your header.
But worse, the DOCTYPE has been completely killed – as it must be the first part of the page – which will trigger quirks mode on your wiki and – depending on how vector is built – may ruin the skin causing visual bugs all over the place that vary from browser to browser, since our skins are not designed for quirks mode.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
On Fri, Mar 7, 2014, at 03:44 AM, Daniel Friesen wrote:
If I understand it right now, Bill is suggesting that you use:
<?php // ... class SkinFubar extends SkinVector { // ... } ?>
<header> My html header code. </header>
Hello Daniel,
Yes, that's what I currently have. I think that's the sort of thing Bill mentioned. I got to the stage that "it works!" and then you came along and made me lookagain :-)
This idea is over 9000% wrong. You're not actually adding anything to the skin at all.
OK, yes. I see what you mean. I must admit there was something that didn't seem quite right about this but, like I said, I have little understanding of the code/skinning (or PHP itself) at the moment. I'll try and sort it out, reverting to the longer but better way.
Cheers,
On Fri, Mar 7, 2014 at 6:44 AM, Daniel Friesen daniel@nadir-seen-fire.com wrote:
On 2014-03-07, 1:13 AM, Alastair Sherringham wrote:
That's probably due to the absolute positioning that Vector's css uses. You'll have to add some extra css of your own to tweak the top position of stuff, or add a relative positioned wrapper around vector's normal content to contain the absolute position within a box you can push down.
Yes, I think I need to look at some CSS and re-position.
A quick question - Bill's way of adding a header/banner is just to write some HTML directly after the very minimal PHP code as per your tutorial (i.e. after "class SkinZedDocs extends SkinVector {", terminated). This is a much smaller and simpler file obviously that copying all the template code from Vector.php. If one only wants to add a banner/header to the output, is there any reason to do it the "long" way over the short and sweet way?
Now that I think I actually understand what you're asking I'll answer your question.
If I understand it right now, Bill is suggesting that you use:
<?php // ... class SkinFubar extends SkinVector { // ... } ?>
<header> My html header code. </header> ...
This idea is over 9000% wrong. You're not actually adding anything to the skin at all.
I have no doubt that this method of getting a header on the page is incorrect, but I found myself in a position where I simply needed to re-implement the header from an old MW install in order to upgrade to 1.22.3. This quick and dirty hack allowed me to move the MW software forward first and deal with fixing the skin at a later date.
The html is simply being echoed whenever the php file is loaded, which is typically the first time SkinFubar is needed. This happens even if the skin isn't used, just as long as it's autoloaded, and is not present if the skin is used to render multiple pages (like DumpHTML).
This definitely happens in my case and causes a slowdown of page load as well.
In one circumstance this can lead to the "headers have already been sent" fatal error as it's possible that the echoed html is output before we define our HTTP headers. Otherwise, ie: if ob_start() happened to be called and collected that text, what happens is this supposed header is really garbage (the technical jargon type) that gets output before any of the skin's html is output.
When I turn on errors, I do see the warning:
Warning: Cannot modify header information - headers already sent by (output started at <myskin>.skin.php:222) in includes/WebResponse.php on line 38
Which really means that your "header" looks about like this:
<header> My html header code. </header> ... <!DOCTYPE html> <html ...> ...
This html is completely invalid. The entire page <head> is now part of an implicitly inserted empty <body>, any class defined on <html> or
<body> probably won't even target the DOM in your header.
But worse, the DOCTYPE has been completely killed - as it must be the first part of the page - which will trigger quirks mode on your wiki and
- depending on how vector is built - may ruin the skin causing visual
bugs all over the place that vary from browser to browser, since our skins are not designed for quirks mode.
I'd love to fix my custom skin and do it the "right" way, but I'm still learning.
~Daniel Friesen (Dantman, Nadir-Seen-Fire) [http://danielfriesen.name/]
MediaWiki-l mailing list MediaWiki-l@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-l
mediawiki-l@lists.wikimedia.org