HTML Logo by World Wide Web Consortium ( Click to learn more about our commitment to accessibility and standards.

Moving forward with Composr

ocPortal has been relaunched as Composr CMS. ocPortal 9 is superseded by Composr 10.

Head over to for our new site, and to our migration roadmap. Existing ocPortal member accounts have been mirrored.

On-going configuration and maintenance

Use this space to share information relating to on-going configuration and maintenance

In addition to the community-editable documentation above, we have the following official tutorials:

  • Backing up your site
    How to backup your website (be it using our backup module, or otherwise), and why it is so important to do it.
  • Providing featured content
    How to pull out content from your website, and put it in a featured spot. There are a number of methods available.
  • The staff/member divide
    A discussion on the features ocPortal provides for members, and for staff - and how permissions divide them.
  • Access control and privileges
    A detailed explanation of how you can configure permissions, how to test them, and how to manage them.
  • Linux file permissions
    The theory behind the permissions ocPortal needs on most web hosts, and practical guidance on setting them.
  • Manually editing your database
    A primer on databases, and how SQL is used to connect to them - as well as practical advice on using phpMyAdmin.
  • Improving your search engine rank
    For most web sites, it is important to draw in visitors. We discuss the process of Search Engine Optimisation (SEO).
  • Creating sub-communities/sub-sites
    A common features of the largest community sites is to have sub-communities within the larger community. See how.
  • Cleanup tools
    Been editing files manually, and need to force ocPortal to "empty its caches"? We show you how.

There are no pages beneath this page

Submitted by Jean
This falls under "Access control and privileges"

There are several things you can do to restrict Menu Items from displaying on your site based on group permissions. Here is a "Quick Tutorial" I've made to illustrate some options:

Submitted by Chris Graham
People often have questions regarding Google Webmaster Tools. The following simulated discussion goes through some of the concerns ocPortal users sometimes have…

There are many errors in Google Webmaster Tools about how googlebot is failing to properly index my website.

These kinds of errors have nothing to do with hurting your general search ranking, they are only warnings about specific URLs, rather the site as a whole. Any non-trivial site will have many of these errors, if only because sites change over time and Google has old URLs in its database.

It's important to understand that Google doesn't do a lot of negotiation about what exactly it should do with your site. There are a few standards that kind of give it hints, like robots.txt, canonical URLs, nofollow headers, robot meta tags, the XML sitemap, and it doesn't put URLs containing HTTP errors into it's search index, but generally what it does is it trawls through your site repeatedly, noting down all the URLs it finds. It then remembers the URLs and will continue to try them in the future, regardless of whether they are valid anymore.

An anally-retentive attitude isn't wholly bad to SEO, especially if you are tuning pages or crafting how things are linked together – but it doesn't work well if you take Webmaster Tool warnings out of context, as something that needs to be eliminated. Google Webmaster Tools provide these warnings to help you review things in general.

Shouldn't the .htaccess file make sure Google doesn't check stuff it is not allowed to check?

The .htaccess file is only ever read by your server itself. Rules in there can determine the HTTP error codes sent to users (including Google), but it doesn't stop them trying. robots.txt is what things like Google use to determine whether they ought to check particular URLs, but that's outside the scope of ocPortal's operation.

You should not think of Google being given a error as something necessarily wrong with your site. It simply means Google made a request, and received an error response. That is a normal and legitimate thing to happen, especially if it is a 401 "access denied" response. It's a normal part of the web, not a system failure. This is a subtle but important point: Google getting a 401 response is not like a police caution, it is normal and instructional. It is an error with respect to that URL not being accessible, but not an error with respect to a system failure or even implication of a bad link (it is valid to give users a link that returns a 401 response in some cases, for example, telling them to log in).
Submitted by Duck

Merging Entries From One Catalogue To Another

I recently had a situation where I created a Games catalogue but designed it wrong at the start. I had intended to use this catalogue as a multiple reference catalogue within another (i.e. To list what games people play). The problem is I had not sorted the games by any category and with over a hundred entries it would make for a very long selection list. I had a field in the catalogue that listed the genre of the game (FPS, RPG etc)  so I created a new catalogue and this time used the Genre's as categories.

I figured out the list of Catalogue Categories by studying the catalogue_categories table.
Then I ran a bunch of queries to update all my entries of the first catalogue to set them under the categories of the second.

One of the first queries was this:


UPDATE catalogue_entries SET c_name='games' , cc_id=24 WHERE id IN (SELECT ce_id FROM catalogues_efv_long WHERE cv_value='RPG')

To break this down:

I renamed the first games catalogue to games2 so all the entries will need to change to "games" and because the genre was a radio list from defaults in the catalogues they were stored in the catalogues_efv_long table. So my new catalogue_category number for the RPG games is 24 so I read all the genre's I set up as 'RPG' and changed the catalogue and category they belonged to in the entries table.

c_name is the new 'games' catalogue
cc_id = 24 is the category for RPG under the new games catalogue
ce_id = the entry id associated with the entry data
cv_value = the radio list chosen genre as text value.

I just ran the above query several times once for each genre replacing cv_value with the new genre and cc_id with the category that represented the genre

Next step was to change all the other entry values in other tables to point to the new catalogues field ids

So I had the old Games2 catalogue mapped to the following ids (first id number is old field id under games2 and second is new field id number games)

Full Name = 54 = 74
Logo = 56 = 75
Short Name = 61 = 76
URL = 60 = 77
Developer = 58 = 78
Description = 59 = 79

and genre was 57 but this will no longer be needed once they are all moved to their respective categories so I just deleted all entries with the cf_id = 57 from the catalogue_efv_long table when done.

So for full name I would run the following query


UPDATE `catalogue_efv_short` SET `cf_id`=74 WHERE `cf_id`=54

This same basic query is run for the various fields on that table (Short Name, Logo, Developer) obviously changing id's as needed

Then the same basic query is run on other tables holding other info like the catalogue_efv_long_trans table which held descriptions.

Lastly when all is said and done I needed to update the category counts for all the categories in the games home and to do this I just did a select statement (or you could watch your result counts when running the first query that moved them over by genre) for each category and took that count and inserted an entry into the catalogue_childcountcache table using the category id and the count.


INSERT INTO `catalogue_childcountcache`(`cc_id`, `c_num_rec_children`, `c_num_rec_entries`) VALUES (24,0,12)
24 represents the category id for RPG and 12 is the number of entries.

Hope this may be of benefit to others if they need it some day.
Submitted by Chris Graham

Notification security

Notifications broadly fall into 3 categories:
  1. Notifications sent directly to a specific member, relating to them
  2. Privilege-affected notifications, e.g. monitoring a download category, and hence needing access to that category to receive the notification
  3. Staff notifications

To stop ocPortal becoming bloated/over-complex, there is no configurable granularity with Staff notifications. Any one with the "May listen to notifications intended for staff" privilege may receive them.

However, you may come into a situation where you do want some granularity. A nice workaround is to have a staff account with a gmail address, and then use gmail forwarding rules to forward to others based upon subject line.
Submitted by Chris Graham
If you have a large translate table and finding some searches are running slow and causing locks, causing slowness for everyone…

This is a problem that MySQL has with fulltext search.

The inherent problem with fulltext search is that if you:
a) run the fulltext first - you have to spend a lot of time limiting those hits down to those that match other constraints. The time taken doing this can be extreme if only a small percentage (or even 0%) match, especially for a broad match that has potentially 10's of thousands of fulltext hits - it will basically go on for ever because it never hits a maximum and thus never ends the query.
a) run the fulltext last - MySQL can't use the fulltext index effectively, having to throw away large numbers of matches while intersecting against the huge pool of possible rows that matched the weaker constraints.

Or in other terms, calculating the intersection between fulltext hits, and other constraints (e.g. forum permissions, or search context) is unindexable and potentially a vast calculation.

This is a serious problem on large databases, but not noticed by most users.

A workaround is to auto-kill searches that take too long (over 5-10 seconds). It requires server-level MySQL access. That is only a proportion of searches (typically ones with a lot of results, yet none matching the other constraints you are searching against).

1) Put this into your my.cnf/my.ini file:



2) Restart MySQL.

3) Run mysql

4) Run this query: USE <yourdbname>;

5) Run this query:


delimiter |

DROP EVENT IF EXISTS killslowsearches;


        DECLARE done INT DEFAULT 0;
        DECLARE connid INT UNSIGNED;
            WHERE COMMAND = 'Query' AND INFO LIKE '%text_original) AGAINST%' AND TIME >= 5;


        OPEN cur1;

                FETCH cur1 INTO connid;
                IF NOT done THEN
                        KILL connid;
                END IF;
        UNTIL done END REPEAT;
        CLOSE cur1;

An alternate similar workaround is possible in MySQL 5.7+, as MySQL have introduced a query timeout setting.

Yet another workaround might be to switch to InnoDB tables in MySQL 5.6+/MariaDB, but this is untested, and won't stop slow queries (it'll just stop them locking the whole table and slowing other users down).
CEDI change-log Post