DeutschEnglish

Submenu

 - - - By CrazyStat - - -

26. February 2013

Montezuma WordPress Theme: Solve Inline CSS

Filed under: PHP,Wordpress — Tags: , , , , , — Christopher Kramer @ 18:12

I was recently asked, why CSS changes within admin panel of the Montezuma WordPress Theme were not reflected on the frontend.

I found out that there is an issue with Multisites, but no solution. So I digged into the code to solve the issue. As I think it might be useful for somebody, I post here what I found out.

if you are not interested in technical details, just look for what I highlighted 😉

Montezuma theme uses inline CSS

If you look at the HTML Source of your site, you will find the whole CSS inline along with this text:

/*************************************************************************
Default CSS served INLINE because wp-content/uploads is not writable.
This will change once wp-content/uploads is writable
**************************************************************************/

So the issue seems to be simple: Just correct permissions. Something like this:

chown www-data:www-data wp-content/uploads

Unfortunately, this was not the issue here. So why does Montezuma fail to place the static CSS file in wp-content/uploads?

Invalid file type

It took me a while to figure out what Montezuma does. In save_css_file() in includes/admin.php, it uploads/stores the theme’s css using wp_upload_bits(). The first problem in the theme is that it does not catch the resulting error while doing this. It should at least print it somehow. In this case, this would result in “Invalid filetype” (in your language).

So wp_upload_bits() calls wp_check_filetype(). This will call get_allowed_mime_types() for a list of allowed mime types. And this looks like this:

function get_allowed_mime_types() {
        return apply_filters( 'upload_mimes', wp_get_mime_types() );
}

So it calls wp_get_mime_types() for a list of mime types. This will again apply a filter on a list of arrays, which in fact contains css. This is good news, because we want to store a css file…

So one of the filters kicks “css” out. And the short story is that it is upload_mimes. The upload_mimes filter uses a list of allowed extensions that can be edited by the user!

To edit it, open http://example.com/wp-admin/network/settings.php in your browser.  The list of allowed filetypes for uploads is quite at the end of the list of settings. Just add “css” here (space-separated).

I think Montezuma should better overwrite the upload_mimes filter with one that allows css.

If you now save your Montezuma settings, it should successfully create a file http://example.com/wp-content/uploads/montezuma/style.css

But in a Multisite setup, this is not the end of the story.

Montezuma uses CSS per site (in a Multisite setup)

With a multisite setup, it depends in which site-backend you change the Montezuma css. If you login one site, it will create the css for this site. If you log into another site, it will create the css for this site.

So you need to change the css in the backend of every site.

So let’s assume you have a site “de” and a site “en”. Then go to http://example.com/de/wp-admin/themes.php?page=montezuma and change the CSS in the Montezuma settings.
This will create a file like: http://example.com/wp-content/uploads/sites/1/montezuma/style.css

Then log into the next site http://example.com/en/wp-admin/themes.php?page=montezuma and edit the css there as well.
This will create a file like: http://example.com/wp-content/uploads/sites/2/montezuma/style.css

Then the css as you edited it should be used in the frontend.

I guess Montezuma should add an option to use a global css for all sites.

Update: Similar problem: Google Webfont is not loaded

The theme allows you to easily use a google webfont. But it does not load?

The problem is almost the same: It fails writing the .js-file. So go into the network-settings and add “js” to the list of allowed extensions, save the Montezuma settings and it should work.

 

Recommendation

Try my Open Source PHP visitor analytics script CrazyStat.

7. February 2013

Icinga / Nagios: Notify a group of contacts about a group of hosts

In Nagios/Icinga, you can easily define which contacts or contact groups get notified for a certain service in the service definition:

 define service{
        host_name               linux-server
        service_description     check-disk-sda1
        check_command           check-disk!/dev/sda1
        max_check_attempts      5
        check_interval          5
        retry_interval          3
        check_period            24x7
        notification_interval   30
        notification_period     24x7
        notification_options    w,c,r
        contact_groups          linux-admins
        }

(Source of this example: Icinga documentation)

So only contacts of the contact group “linux-admins” would be informed about problems regarding this service.

You could also use the “contacts” directive to list individual contacts or list multiple contact groups.

But often, the responsibility of admins is not defined through services, but through hosts. Usually, there is a group of admins for linux servers and one for windows servers. Or a group for intranet servers and one for internet servers. As admins usually are annoyed if they get notifications about servers they are not responsible for, it is usually a good idea to only notify those admins that are responsible.

So you can also do this at the host-definition:

 define host{
        host_name                       bogus-router
        alias                           Bogus Router #1
        address                         192.168.1.254
        parents                         server-backbone
        check_command                   check-host-alive
        check_interval                  5
        retry_interval                  1
        max_check_attempts              5
        check_period                    24x7
        process_perf_data               0
        retain_nonstatus_information    0
        contact_groups                  router-admins
        notification_interval           30
        notification_period             24x7
        notification_options            d,u,r
        }

(Source of example: icinga documentation)

So only the contact_group “router_admins” would be notified for this host.

But one thing where the “contacts” and “contact_groups” directive is missing, is the hostgroups definition. It is not possible to directly assign a contact group  or list of contacts to a hostgroup or the other way round. So here is how it can be done with another type of definition.

Group your hosts

First, define a group of hosts for each group of admins. So for example, group all intranet servers in one and all internet servers in another group. You probably already did this.

define hostgroup{
        hostgroup_name          intranet-servers
        alias                   Intranet Servers
        members                 intra1, intra2, intra3
}
define hostgroup{
        hostgroup_name          internet-servers
        alias                   Internet Servers
        members                 inter1, inter2, inter3
}

See the icinga documentation for details. Note to use the shortnames in “members”.

You can also define things the other way round: When defining a host, say which hostgroup it belongs to:

define host{
        use                     generic-host
        host_name               intra1
        alias                   intra1.local
        address                 192.168.10.1
        hostgroups              intranet-servers
        }

See documentation for details.

Group your contacts

Next, group your contacts. So create a contact-group for each group of admins so we can later assign this contact group to the corresponding group of hosts.

Example:

define contactgroup{
        contactgroup_name       intranet-admins
        alias                   Intranet Administrators
        members                 alice, bob
        }
define contactgroup{
        contactgroup_name       internet-admins
        alias                   Internet Administrators
        members                 charley
        }

See documentation. Again, you can also define it the other way round (list the contact groups at the contact-definition).

Assign contact groups to host groups

Now comes the interesting part. To do this, we use a “Hostescalation definition“.

Example:

 define hostescalation{
        hostgroup_name          intranet-servers
        first_notification      1
        last_notification       0
        notification_interval   60
        contact_groups          intranet-admins
        }

 define hostescalation{
        hostgroup_name          internet-servers
        first_notification      1
        last_notification       0
        notification_interval   60
        contact_groups          internet-admins
        }

This will make sure internet-admins get informed about internet-servers and intranet-admins about intranet-servers. “last-notification 0” means that all notifications will get sent to this group of contacts. You can adjust the notification_interval (in minutes) if you want.

The cool thing here is that you can also define that if the problem still occurs after 5 notifications, the other team of admins gets notified:

define hostescalation{
        hostgroup_name          intranet-servers
        first_notification      1
        last_notification       3
        notification_interval   30
        contact_groups          intranet-admins
        }
define hostescalation{
        hostgroup_name          intranet-servers
        first_notification      4
        last_notification       0
        notification_interval   60
        contact_groups          internet-admins, intranet-admins
        }

This would notify “intranet-admins” 3 times (every 30 minutes) about problems with “intranet-servers”. If the problem is still not solved, “internet-admins” will get notified as well. So the internet-admins won’t get bothered with short problems that the intranet-admins can fix, but will still get informed if the problem is not solved for some time.

More information on hostescalation and serviceescalation in the documentation here, here and here.

I hope this helped somebody.

5. February 2013

Oxwall Community Software: How to create your own theme

Filed under: PHP — Tags: , , , , , , , , — Christopher Kramer @ 14:45

Oxwall is a great community-software written in PHP. You can easily install it on your own server to build your own community site.

It is open source and you have full control over the data.

Although Oxwall comes with some great themes that can even be easily customized in the backend a bit, one might want to build one’s own theme for Oxwall.

So here is how it’s done:

  1. Probably first build an HTML template of your design (one HTML page with CSS that looks like you plan how your Oxwall should look like). If you do that, make sure to use a list-based main menu and a div/link-based bottom-menu (see below) so you won’t get into trouble later.
  2. Always a good idea to have a backup – although adding a new theme shouldn’t break anything. I’d recommend you to create a copy of your Oxwall installation where you create and test your new theme and when it’s finished, move it to your live installation of Oxwall.
  3. Create a copy of an existing theme. You will find the themes in ow_themes. Choose one you’d like to use as a base for your own theme.
    Copy it. E.g on a linux shell:

    cp -rp ow_themes/spring ow_themes/mytheme

    Of course you could also use FTP or something like that.

  4. Define the meta-data of your theme like name, author and so on. To do so, open ow_themes/mytheme/theme.xml in a text editor and adjust the data. Make sure the <key> is equal to the foldername (“mytheme” in the example).
  5. If you want to, you can replace the theme_preview.jpg with a small thumbnail representing your theme (optional).
  6. Now you can select this theme in the Oxwall backend. Try it.
  7. Note: To be able to adjust the theme, enable DEV_MODE. Otherwise you won’t see any changes. So open ow_includes/config.php in a texteditor. Search for:
    else
    {
        /**
        * Make changes in this block if you want to enable DEV mode and DEBUG mode
        */
    
        define('OW_DEBUG_MODE', false);
        define('OW_DEV_MODE', false);
        define('OW_PROFILER_ENABLE', false);
    }

    Change OW_DEV_MODE to true:

    else
    {
        /**
        * Make changes in this block if you want to enable DEV mode and DEBUG mode
        */
    
        define('OW_DEBUG_MODE', false);
        define('OW_DEV_MODE', true); /* HERE! */
        define('OW_PROFILER_ENABLE', false);
    }
  8. Now you can start to adjust your theme. So what does a theme consist of?

Meta-Data: theme.xml

Like said, theme.xml contains the meta data and theme_preview.jpg is a preview image.

CSS: base.css

The main css of a stylesheet is called base.css. You can change/adjust the css there (there are also other places like the backend). I would recommend you to keep the css of your base theme and only adjust and add things to it. Otherwise you’ll have a hard time styling lots of things.

Images: images/*

If you need to include images, this is the best place to put them. If you refer to them from the css, use a path like this:

background-image: url(images/myimage.jpg);

HTML: master_pages/*

The HTML that builds your theme is stored in master_pages.

Note: Lots of themes do not contain all master_pages. If one is missing, the master_pages of the graphite theme are used. Therefore, I’d recommend you to first copy missing master_pages from the graphite theme to your theme so you get a full set of master_pages.

The following master_pages can be there:

  • admin.html (only for the admin backend – no need to adjust this)
  • blank.html (usually no need to change this as well)
  • dndindex.html (body for  pages without sidebar – you’ll want to adjust this!)
  • general.html (body for pages with sidebar – you’ll want to adjust this!)
  • html_document.html (html-head of all pages, you might want to add css or javascript here)

Markers

The following are the most important markers that you can put into your html master_pages:

{$siteUrl}

{*$siteName*}

{*$siteTagline*}

{component class=’BASE_CMP_Console’}

This is the console containing “Login”, “Register” and so on (usually at the top right corner).

{$main_menu}

A list-based menu.
Hint: Listamatic has lots of great list-based menu examples.

{$heading}

{component}

The sidebar.
Note: only in general.html

{add_content key=’base.add_page_top_content’}
{$content}
{add_content key=’base.add_page_bottom_content’}

These 3 build up the main content.
Note: You’ll only need {$content} in dndindex.html

{$bottom_menu}

The bottom menu.
Note: Not list-style, but a div with links.

{text key=’base+copyright’}

{$bottomPoweredByLink}

{decorator name=’floatbox’}

This should be at the end of your html file – oxwall puts some JavaScript and stuff like that there (for chat etc.).

All the others should be self-explaining.

So how you could do it:

  1. Upload your images to “images” and your js (of any) to the theme-folder
  2. Add your css at the end of base.css
  3. Add your references to additional css / js to html_document.html (no need to add a reference to base.css!)
  4. Put the content of your body into general.html and dndindex.html
  5. Replace your static content in there with markers.

Don’t forget DEV_MODE

When you are done, don’t forget to set DEV_MODE back to false. Otherwise your site will load slowly.

If this was of help for you or you still have a question, please let me know.

You can also contact me if you need someone to do an Oxwall theme for you.