Everything posted by Rikki
-
Highlighting staff posts to improve communication
Whatever the purpose of a community - be it customer support, fan engagement, interest-based groups and so on - there's usually a need for site staff to communicate important information to users. Of course, in some cases this information is best suited to a site announcement, which by design has a lot of visibility and authority. But it's important that day to day staff posts stand out too. As we'll discuss in future articles, a key part of engagement is that users see your organization's team interacting with the community. In many cases, users will expect and appreciate acknowledgement from your community team, and by highlighting those responses you can add a visible stamp of authority. Invision Community has a few different tools to help you highlight staff posts, so let's take a look at them in more detail. Group badges With group badges you can upload a small image that is shown beside a user's posts. It's shown alongside the user's group name, so you don't need to repeat that text. Each group can have a different badge, perfect for communities that structure their staff groups based on role type. It's common to color-code group badges for easier identification - support as green, product development as blue, and so on (and you may want to coordinate these colors with the prefix and suffix you use, which we cover later in this article). It's not just staff groups that can have badges, either; your regular member groups can too. However, a word of caution! If every group has a badge, they may lose their distinctiveness. We recommend reserving group badges for those groups you specifically want to draw attention to. Post highlights Second is a feature more explicitly designed to highlight a post rather than simply draw attention to the author. Group settings in Invision Community enable you to choose to have posts by users in each group show with a distinctive background color and border. The color is defined by your theme and so is easily configurable, too. As with group badges, it may be tempting to highlight every group's content, but we recommend not doing so as that reduces the overall impact of the feature. Keep it reserved for your key staff groups, and especially those that regularly interact with the community. Group prefix/suffix Invision Community allows you to define a custom prefix and suffix for each group. This is used in key locations, including to highlight usernames in the Active User block and to style member group names alongside content. An important part of this feature is that it accepts HTML tags, which gives you a lot of scope for customizing the display by adding an opening and closing HTML tag to the prefix and suffix settings, respectively. For example, let's say we want to add a shield icon before the name, and make the text purple. Prefix: <span style='color: #9013FE'><i class='fa fa-shield'></i> Suffix: </span> Simple! Now our staff members will display in the Active User block and elsewhere like this: Bonus feature: Staff activity streams I wanted to also mention a feature that achieves a slightly different goal to those we covered above, but nonetheless is an important way to bring additional visibility to staff content: activity streams. As well as an overall “All Activity” stream that shows everything happening in the community, Invision Community allows you to define pre-made streams that are available to all users. You can use this to build streams of content with particular tags, certain types of content - or, as in this case, content by users in specific groups. Simply create a new activity stream in the Admin Control Panel, set the configuration so that it only pulls content from members in your staff groups, and you're done. Users will now be able to visit the stream page to get a handy overview of everything staff members are doing in your community. I recommend checking out the other filter options available for streams while you're setting this up - there's a huge amount of power available! Summing up I hope this quick overview of content highlighting features has been useful. When users visit your community, they're usually looking for authoritative information and that often comes right from your own team. By utilizing the features we've discussed here, you can make that information stand out more against the other content in your community.
-
Proactive and reactive moderation - which is right for your online community?
One of the bigger decisions a community manager has to make as a community grows is whether to employ proactive or reactive moderation (or a combination of both). This isn’t always a conscious decision; sometimes forum moderation features are toggled without giving much explicit thought to the style of moderation desired and the pros and cons of doing so. It’s worth taking a moment to consider the reasons behind each type, and come to a justification for one or the other. Firstly, let’s discuss what we mean by proactive and reactive moderation. Proactive Moderation With a proactive approach to moderation, the goal is to prevent bad content from ever appearing in public. The primary way that this is achieved is by having moderation staff review all content posted, and manually approving it after deciding whether it is acceptable. Another feature that could be classed as proactive moderation is administrator screening of new registrations. When a new user registers in the community, their account can be placed in a ‘validating’ state, requiring an administrator to review the information submitted and deciding whether to approve the account. As you might expect, proactive moderation is the safest way to ensure bad content doesn’t make it to public view. However, the significant drawback is that users won’t see their content immediately, which can be frustrating and severely stifle productive discussion. At worst, it can push users away from your community altogether. Heavy-handed moderation is often viewed negatively by members who are trying to participate, and can ultimately backfire. With a proactive moderation approach, it’s important that you communicate with members one-to-one if they post content with good intentions but which doesn’t meet your criteria. This can reduce resentment over wasted effort, and gives them the opportunity to adjust their approach for future content. Reactive Moderation In contrast, a reactive approach to moderation allows user to post freely, without explicit pre-screening of content, with moderators reacting to issues as and when they arise. Reactive moderation is, generally speaking, a more pleasant experience for users because it allows them to engage fully with the community. However, there is of course the risk that unsuitable content is seen in public, at least temporarily. Choosing a reactive approach doesn’t have to mean a free-for-all. There are many features you can use to make identifying and dealing with bad content a quick and painless process, while still allowing users to contribute freely to the community: Report center Allows users to identify bad content and submit notifications to moderation staff for prompt action. Badword filter, URL filtering and keyword triggers Prevent common swear words and other divisive terms from being used by censoring them or replacing them with ***. You can also blacklist undesirable URLs from being used within posts. Plus, automatically watch and moderate posts that contain terms you specify. Warning system Where a user has proven to be problematic, the warning system in Invision Community allows you to track infractions and apply punishments to the account. These can range from a simple warning message, to suspension, to complete ban. Users can be required to acknowledge the warning before being able to see the community again. Moderation queue Individual users can be placed into the moderation queue, requiring all content they post to be screened by a moderator before being visible - a good compromise that means you don’t need to screen all content, just that from troublemakers. Spam service The IPS Spam Defense Service is a free service that automatically reviews new registrations to your community to determine whether they match any known spammers, using data crowdsourced from other Invision Community sites. The service can virtually eliminate known spammers from your community, preventing them from ever causing a problem. One-click spam cleanup If a spammer does make it into your community, removing their posts and banning them is a one-click action for moderators. Saved actions Saved actions make it quick to apply multiple moderation actions in one go. For example, if members often post support topics in a non-support forum, a saved action would allow moderators to move the topic and reply to let the member know what happened - all with a single click. Which is the right approach for your community? Every community is different, so there’s no one answer here - that’s why Invision Community includes features that enable both approaches, to allow you to determine which to use. In general, we suggest thinking of reactive moderation as the default stance, and increasing the amount of oversight you make depending on the circumstances. There are exceptions of course. For example, in a situation where a user posting personally-identifying information in a public forum could have a profound implication for personal safety, a proactive moderation approach might be more desirable. Similarly, if it’s essential that users receive correct information that has been vetted by your staff, you may want to review content before it appears (though in this case, other techniques might be considered, such as staff labelling content once it is ‘approved’ by them). Your choice need not be entirely one or the other, either. While Invision Community has moderation settings that apply to the entire community, it’s also possible to apply different settings on a per-forum or per-member group basis. Communities often make use of per-group moderation as a way of screening new members. This is achieved by putting new members into a ‘limited’ group that requires content to be reviewed by a moderator. Then, using Invision Community’s group promotion tools, the member is automatically moved to a regular member group once they have a specified number of approved posts (usually a low number; one to five works well). This approach reduces the danger of a rogue member signing up and creating a problem, without requiring the resources to screen every new post to the community. Finally, whichever approach to moderation your team ultimately finds work best, we recommend creating a clear, detailed set of community guidelines that outlines the boundaries of the community, and what you consider acceptable and unacceptable from members. Most users don’t set out to create problems for you, and referring to your guidelines can often put the lid on any trouble before it starts. We hope this overview proves helpful to both new and established communities. If you have any approaches to moderation that you think others might be able to learn from, please go ahead and share them in the comments below!
-
New: Richer Embeds
This is an entry about our IPS Community Suite 4.2 release. You are probably already familiar with our content embedding feature in IPS Community Suite. When a link to content in the community is pasted into the editor (e.g. a topic, or a post, or a gallery image, etc.) it is automatically expanded into a preview of the content, usually with an accompanying image, allowing users to click through to that content if they are interested. An embedded Gallery image in IPS Community Suite 4.1 While it has proved a useful feature to members, each embed used essentially the same structure - a small thumbnail on the left, a title, and a few lines of text. This works fine for topics, but isn't ideal for other kinds of rich content that might be posted. In IPS Community Suite 4.2, we greatly improved upon our embedding handling, giving every type of content within every application its own customized embed style, allowing that content to be displayed however works best. This means larger high-res previews of Gallery images, a button to download a file right from the embed for Downloads files, showing a map for Calendar events, and so on. We worked to keep a consistent overall style between apps, but allow each to display its own relevant information. For users, things will work exactly as they do now - they simply paste a link to content, and it will continue to expand automatically. The changes are also backwards compatible. Any existing embeds in your community will automatically show the new styling you see below - no rebuilding necessary. So with that in mind, let's take a look what the new embeds look like! I won't show every single embed here because there's a huge number, but I'll try and give you a feel for how we approached the embed styles for each app. Gallery Image Comment on a Gallery Image Gallery Album Forum Topic Downloads File Review on a Downloads File Calendar Event Comment on a Calendar Event Commerce Product Record from a Pages database I hope that gives you a good overview of what to expect when your users try out the new embeds for themselves. As always, please share your feedback in the comments below!
-
New: Clubs
This entry is about our IPS Community Suite 4.2 release. We are happy to introduce the next major feature that will be available in IPS Community Suite 4.2 - Clubs. Clubs are a brand new way of supporting sub-communities within your site. Many people have requested social group functionality in the past and Clubs are our implementation of this concept. Let's take a look at a few screenshots, and then go over what they are capable of doing. The Club directory A Club homepage Club member listing Example of content within a club (topics, in this case) There's a lot to digest there! Let's go over the basic functionality. Club Types Four types of club are available: Public clubs Clubs that anyone can see and participate in without joining. Open club Clubs that anyone can see and join. Closed club Clubs that anyone can see in the directory, but joining must be approved by a Club Leader or Club Moderator. Non-club-members who view the club will only see the member list - not the recent activity or content areas. Private club Clubs that do not show in public, and users must be invited by a Club Leader or Club Moderator As the site admin, you can of course configure which club types can be created and by whom. You could, for example, allow members to create public and open clubs, but allow a "VIP" group to also create Closed and Private clubs. Admin configuration option for Club creations Club Users Each club has three levels of user: Leader A leader has all of the permissions of a moderator, and can add other moderators. They can also add content areas (see below). The club owner is automatically a leader. Moderators Moderators, as the name implies, have the ability to moderate content posted within the club. As the site administrator, you can define which moderator tools can be used. You could, for example, prevent any content being deleted from clubs, but allow it to be hidden. Moderators can also remove members from a club. Users Anyone else that joins the club. Defining the moderator permissions available to club moderators Your site administrator and moderators, with the appropriate permissions, are able to moderator content in any Club regardless of whether they are a member of it. Clubs can be created by any user who has permission. As you would expect, this is controlled by our regular permission settings. For closed clubs, there's an approval process. Users can request to join and the request must be approved by a leader. Leaders get a notification when a user requests to join; the user gets a notification when their request is approved or denied. Approving and declining join requests Club Content Club Leaders can add a variety of content areas to their club - forums, calendars, blogs and so on. It's important to note that these content areas are fully functional just as if they existed as a top-level admin created area. They will appear in search results, activity streams, users can follow them, embed links to them, and so on. If a user has permission to see a forum (for example) within a club it will behave exactly like other forums they see - and the same for all other kinds of content. Each content area a leader adds can have a custom title, and will appear in the club navigation. This means, for example, that you can have multiple forums within a club, and give each a different name. Adding content areas to a club Club Custom Fields Clubs also support custom fields. Custom fields are defined by the site administrator and can be filled in by Club Owners. The values they enter are shown (along with the club description) on the club homepage. Custom fields in a club On the Club Directory page, users can filter by the custom club fields. Filtering clubs Club Locations Clubs have built-in support for Google Maps, allowing users to specify a physical location for their club. Let's say you run a community for car enthusiasts; each club might be tied to a particular region's meetup. The Club Owner specifies the location when setting up the club, and clubs are then shown on map on the directory page: Club locations And within a club, the location is shown too: Club Display We offer two ways to display club headers within the club - the standard way, shown in the screenshots you've seen up to this point, but we also have a sidebar option. This is something the admin sets globally for the site, rather than per-club. This is useful where your site design doesn't facilitate another horizontal banner taking up valuable screen real-estate; moving the club banner to the sidebar alleviates this pressure on vertical space. Sidebar club style Using Clubs in Other Ways There's a lot of scope for using clubs beyond allowing users to create their own groups. You do not even have to call them "clubs" if that does not suit your use case. For example, on a company intranet you could rename Clubs to "Departments", and create a private group for each of your main roles. This would allow each department to have its own community, with its own forums, gallery, file sharing and so on, private and separate from other departments. Similarly, they'd also work well in situations where you as the site admin want to create entire micro-communities. Take for example a video game publisher. Using Clubs, they could create a micro-community for each of their games, complete with forums, galleries and so forth, and then set the Clubs directory as their overall community homepage. Immediately, they have a setup that hasn't until now been possible out-of-the-box with IPS Community Suite. We expect our clients will come up with some really innovative uses for the new Club functionality, and we can't wait to see what you do. We'd love to hear your feedback - let us know what you think in the comments.
-
New: Reactions
This entry is about our IPS Community Suite 4.2 release. IPS Community Suite has long had a reputation system; first we had a simple up/down system, later updated to introduce a Likes system as an alternative. Whichever system you chose to use, it tied in with our reputation system. We're pleased to introduce the latest updates to the reputation system, and it's something that has been requested for quite some time: Reactions. Quite simply, reactions allow users to offer more fine-grained sentiments towards content than a simple up/down or 'like'. They are now in common usage on social networks, and so users expect to be able to be more nuanced in their response to something they see. Let's see how they work in a post, and then cover the options you'll have available. What you see above is the default setup for a site that has used the Like system in version 4.1. We include 5 reactions by default: Like Thanks Confused Sad Haha If you currently use the older style up/down reputation system, don't fret - you'll still get the new reactions on upgrade, but they'll be disabled by default and instead the new reaction UI will show up/down reactions. This gives you the flexibility to decide which of the new reactions, if any, you want to allow. So, those are the basics - but what configuration options can you expect to see? First, you can of course add your own reactions! We expect that beyond the default reactions you'd expect to find, some sites will want reaction types specific to their use-case. On an intranet, you might want to have 'agree' and 'disagree' reactions for staff to use when responding to discussions. On a gaming community, you might replace the icons to be some graphic from a video game that means something to your particular userbase. There's a wealth of possibilities. Each reaction you set up can be configured to adjust the original author's reputation count - a reaction can be positive (i.e. award a reputation point), negative (i.e. subtract a reputation point), or neutral (i.e. leave the reputation count unchanged). Our default set won't include any negative reactions, but you are free to configure these and new reactions to suit your own use-case. A user's total reputation count is still shown alongside their content and in their profile, of course. If you don't want to use the new reactions for whatever reason, you can disable all of them except Like, and it'll behave just the like 4.1-and-earlier system: Sites that currently use the up/down system don't show a list of names of users, and instead show an overall reputation score for the content. With the new reaction system, you can enable this even if you don't use up/down reactions. This is great if you plan to use reactions as, for example, an agree/disagree system, or where the content score is more important to your site than the individual reaction types. How the reaction UI looks with the 'count only' setting enabled As you'd expect, you can click individual reaction counts (or the overall reputation score, if you enable that setting) to view who reacted to the content. This remains a permission setting that you can apply per-group. On touch devices, on-hover functionality is not suitable, and so for these devices the reactions UI looks like this: Reactions play well with all areas of the suite, including Recommended Replies: ...and activity streams... ...and a couple of places we aren't quite ready to reveal yet We hope you're looking forward to this new feature as much as we are. It's already been a hit on our internal testing site, and we're looking forward to seeing how clients customize it for use on their own community. Developer note: Reactions are one of two new features (the other currently unannounced) so far that make use of PHP Traits.
-
Mixins
Mixins are a special type of controller that allow you to augment or change the functionality of an existing controller. This is particularly useful when you need to change something about how a built-in controller works. Basic structure This is the boilerplate for a mixin: ;( function($, _, undefined){ "use strict"; ips.controller.mixin('mixinName', 'core.global.core.table', true, function () { // Your code goes here }); }(jQuery, _)); The method signature is: ips.controller.mixin( string mixinName, string extendsController, boolean autoLoad, function mixinBody ) mixinName A name that will refer to this mixin extendsController The full name of the controller that this mixin will extend (e.g. core.global.core.table) autoLoad Boolean indicating whether this mixin should always extend the extendsController controller, or only when specified mixinBody A function that returns the behaviors that the mixin defines How a mixin works A mixin works by allowing you to provide custom code that will execute at key points when the parent controller's method is called. To do that, there are three important methods available to a mixin: before() Run the specified code before the parent controller's method after() Run the specified code after the parent controller's method around() The specified code is passed a reference to the parent controller's method, allowing it to be called when desired (and the return value modified In addition to hooking into existing controller methods, your mixin can also provide new methods for its own use and, notably, simply redefine a method present in the parent controller in order to completely replace its functionality. A note about this Within the mixin body, you'll be adding methods to this. The mixin executes in the same context as the parent controller; that is, this in a mixin refers to both the mixin and the controller it extends, allowing you to call methods from the controller, and any create yourself in the mixin. During execution, they are one and the same. The same is also true within methods in your mixin since, like in controllers, methods are automatically bound to the controller for you. You may be familiar with this.scope in controller methods (which refers to the DOM element onto which the controller is applied). Since mixin methods are bound in exactly the same way, using this.scope in a mixin method will still give you the element onto which the controller is applied. before() and after() The behavior of these two methods are very similar. They simply allow you to execute your custom code either immediately before, or immediately after the parent controller's code. Your custom code receives the parameters that are passed into the parent method, but not the return value (if any). A common usage of either method is to add additional event handlers to a controller. A controller sets up its event handlers in the initialize method, and so a mixin can add more handlers like so: this.before('initialize', function () { this.on('click', '#button', this._doSomething); this.on('click', '#button2', this._doSomethingElse); }); In this case, our function will be executed, and then the parent's own initialize method will be executed. In this example we don't deal with any parameters but, if the parent method is called with any, they will also be available to your mixin function as normal parameters, in the same order. around() This behaves differently to the previous example, because rather than simply being executed before or after the parent, it actually provides the parent method as a reference to your own function. This allows you to call the parent method at a time of your choosing - perhaps determined based on some logic in your code. Since you have control over calling the parent method, you also have access to its return value, meaning that around can also be used as a way to modify the value that is returned from a controller method. As an example, let's assume that the parent controller method returns a JSON object, but we want to augment this with some additional key/values. We can do this using the around call, like so: this.around('parentMethod', function (origFn) { var returned = origFn(); return _.extend( returned, { key1: true, key2: false }); }); Notice that the parent method is passed in as a parameter (if the method has any other parameters, these will appear first, and the parent method will be the last parameter). We call this method in order to get its return value for our own use. When we look at the parent method we know that it returns a JSON object, so we extend it with our own values. It's worth noting that since you receive both the original parameters, and a reference to the parent method, you have the ability to modify the parameter values before passing them into the parent method. This approach can offer a lot of flexibility. Custom methods and replacing existing methods Finally, you can create new methods in your mixin, or completely replace methods from the parent controller by redefining them. In both cases, this is done like so: this.myMethod = function () { //... }; Of course, if you replace an existing method, be sure it plays nicely with any calls to it! Calling a mixin Mixins can be applied to controllers manually when needed (you don't need to do this if you configured your mixing to automatically apply to the controller, though). To do so, specify the mixin name in parenthesis after the controller. For example: <div data-controller='core.front.core.someController( mixinName )'> </div> Multiple mixins can be provided if they are comma-delimited. Note that mixin files are not loaded on demand in the same way that controller files may be (but they will be compiled into bundles in the same way at build-time). In order for a mixin to be applied, it must be included in the page output. This means that if you're creating a plugin that (for example) has a mixin that applies to a core controller, you are responsible for ensuring the mixin file is included in the page as needed. This may mean creating a theme hook that modifies the output of the includeJS template.
-
Common logic checks using HTML Logic
HTML Logic is a very powerful way of conditionally showing different elements in your theme, depending on the values of certain properties. Since the entire IPS4 framework is available within a logic expression, there's a lot of scope for using different kinds of data to determine what should show. In this guide we'll provide a range of examples of common logic checks you might want to do. Even if the exact expression you need isn't listed here, it should provide a good starting point to help you write your own expressions. Logic Recap Let's quickly recap how HTML Logic works. For a more complete tutorial, be sure to read through the Template Syntax guide. In IPS4, logic checks are done using the special {{if}}, {{else}} and {{elseif}} tags. As with standard programming logic, if the expression results in true, the block of code within is executed. If it is false, it isn't (and if there's an else or elseif block, that is tested for a true result instead). So, a block of logic in a template might look like this: {{if member.member_id == 3}} <!-- If the member has ID 3, this will be shown --> {{elseif member.member_id == 9}} <!-- But if the member has ID 9, this will be shown instead --> {{else}} <!-- If the member isn't ID 3 or 9, then this will show --> {{endif}} If you need help constructing a logic check, feel free to check out the Customization Resources forum. Examples. I want to... Check if the user is logged in {{if member.member_id}} <!-- this will show if the member is logged in --> {{endif}} Check if the user isn't logged in {{if !member.member_id}} <!-- this will show if the user is a guest --> {{endif}} Check if the user's ID is one of x, y or z You can check as many values as you like; just add more numbers to the array. {{if in_array( member.member_id, array( 5, 28, 472 ) )}} <!-- Shows if the member's ID is 5, 28 or 472 --> {{endif}} Check if the user is in group x Where x is the group ID number. Note that this also checks secondary member groups. {{if member.inGroup('x')}} <!-- Shows if member is in group 'x' --> {{endif}} Check if the user has more than x posts In IPS4, all content in all apps counts as a 'post'. {{if member.member_posts > 3}} <!-- Shows if the member has more than 3 posts --> {{endif}} Check if the user has fewer than x posts In IPS4, all content in all apps counts as a 'post'. {{if member.member_posts < 3}} <!-- Shows if the member has fewer than 3 posts --> {{endif}} Check if the user is an administrator Note that this also checks if any of the user's secondary member groups has admin permissions. {{if member.isAdmin()}} <!-- Shows if the user is an administrator --> {{endif}} Check if the user is banned {{if member.isBanned()}} <!-- Shows if the user is banned --> {{endif}} Check if the current page is part of app x You need to check the application key. Most are obvious (e.g. forums is the forums app), but there are some others to be aware of. For custom/third-party apps, ask the author which app key they use. core = Any system page that isn't part of another app, e.g. search, login/registration, profiles etc. cms = Pages nexus = Commerce {{if request.app == 'forums'}} <!-- Shows if the user is viewing any page in the 'forums' app --> {{endif}} Check if a system setting has value x You can check whether system settings have a given value, although you will need to know the setting key used by the backend. Values may not be simple to check, depending on their type - consult our Customization Resources forum if you aren't sure how to check a particular setting. {{if settings.auto_polling_enabled}} <!-- Shows if the 'auto_polling_enabled' setting is true (i.e. enabled) --> {{endif}} Check a variable in a template has value x Template bits in IPS4 may receive one or more variables from the backend code. You can check the values of these within the template to do something based on the value. This only works within the template into which the variable you are checking is passed - they are not inherited. {{if $myVariable == 'some_value'}} <!-- Shows if $myVariable is equal to 'some_value' --> {{endif}} Check if the current forum is forum ID x Within the forums app, you can check whether the current page is showing the forum with ID x {{if request.app == 'forums' && request.module == 'forums' && request.id == 3}} <!-- Shows if the user is in the forums app, viewing a forum with the ID 3 --> {{endif}} .
-
Introducing our new Developers area
I'm pleased to announce we're finally ready to open our new Developers area. The aim of this project has been to improve our existing developer documentation by building a central place to contain it, as well as update and expand the content available. As of today, we have the regular documentation and REST API documentation ready to use. Over the coming weeks and months, we'll be expanding what's available further, going into more detail about the tools available within the framework. We've also started work on comprehensive Getting Started guides, that will walk you through simple developer projects from start to finish - these will be available soon, once they're complete. If there's a particular aspect of IPS4 development that you don't feel is adequately catered for right now, please let us know! This will help us direct our efforts to the most useful places. Enjoy!
-
Theme Tip: Color coding tags
We were recently asked if it's possible to color code tags - the customer in question used tags as statuses on topics, and so wanted 'resolved' to be green, and so on. Despite being a great idea, this isn't something that is currently possible 'out of the box' - although we'll add it to our internal feature idea list to follow up on later! But just because it isn't built in, that doesn't mean it isn't possible! In fact, with a little CSS, this is quite easy to achieve now. Writing a CSS selector We can do this by writing a CSS selector that matches the tag URL for the tag we want to style - a handy way to use CSS that can be applied to lots of other ideas within the suite! Lets say we have a tag called 'resolved', and we want to make it green. Add the following CSS to your custom.css file: .ipsTags a[href*="/tags/resolved/"] { background: SeaGreen; } html[dir="ltr"] .ipsTags a[href*="/tags/resolved/"]:before { border-color: transparent SeaGreen transparent transparent; } The first style is the main part of the tag element; the second matches the :before pseudo-selector which we use to make the 'point' of the tag. Another tag we'll style is called 'needs help'. In this case, there's spaces in the name, which are represented by the + symbol in the URL (since it's URL-encoded). We'll make it purple this time: .ipsTags a[href*="/tags/needs+help/"] { background: Purple; } html[dir="ltr"] .ipsTags a[href*="/tags/needs+help/"]:before { border-color: transparent Purple transparent transparent; } Supporting prefixes This little CSS snippet won't change prefixes, however - they'll still be shown in the default color (specified by your theme settings). If you want to change prefixes too, you need to adjust the CSS as follows - replace the previous CSS with this version: .ipsTags a[href*="/tags/needs+help/"], a.ipsTag_prefix[href*="?tags=needs+help"] { background: Purple; } html[dir="ltr"] .ipsTags a[href*="/tags/needs+help/"]:before, html[dir="ltr"] a.ipsTag_prefix[href*="?tags=needs+help"]:before { border-color: transparent Purple transparent transparent; } (Note: Notice the slightly different string we're matching in the href attribute; once you upgrade to 4.1.14, this won't be necessary - both selectors can use the same href format, e.g. /tags/needs+help/. Prior to 4.1.14, tags and prefixes used slightly different URL formats.) That's it - now everything looks correct! Topic View Forum View
-
Theme Tip: Create a per-forum feed block
An enterprise customer recently asked us how to have a different feed block for each of their forums. Their goal was to have each forum show a 'popular topics' block containing topics only from that particular forum. Unfortunately this isn't possible using the standard block manager right now, since each view is treated as one configuration. That means that any blocks added to forum view will show for all forums. However, as usual in IPS4, some of the more advanced power under the hood does allow you to achieve the same goal - in this case, by using HTML Logic. This technique uses a similar idea to the one I outlined in the Dynamic-ish Forum Feeds blog in May. Creating conditional blocks The way we would implement this functionality is by creating a custom block that is simply a wrapper for other blocks. This wrapper block will contain HTML Logic that determines which feed block to show, based on some information about the current page. The first step would be to create standard feed blocks for each of the forums to which this should apply. In our example we're creating 'popular topics' blocks, but it could be anything you wish - the principle will remain the same. Another idea would be to create a 'Topics from other forums' block for each of your forums, whereby in the block configuration, you set it to include topics from all forums except the one in which it will be displayed - a good way of cross-promoting your topics. In order to include the blocks later, set the template key of each to be forum_x, where x is the ID of the forum in which you will display the block. Once we've created a block for each forum, the next step is to create our wrapper block, which should be a custom block set to use Manual HTML, with the following code: {{if request.app == 'forums' && request.module == 'forums'}} {{$id = \IPS\Request::i()->id;}} {block="forum_{$id}"} {{endif}} What's happening here is we're checking the app and module from the page URL are both 'forums', which indicates we're in forum view. We then use the {block} tag to insert the appropriate block based on the ID parameter from the URL. To use this block, simply save it, then using the Block Manager on the front-end, drag it into the desired location in your forum view. I hope this quick suggestion gives you some ideas for other ways to create blocks that show contextually depending on what the user is viewing. If you have ideas for interesting ways to use this technique, share them in the comments!
-
New in 4.1.13: Personal Messenger Improvements
In line with our aim to make incremental improvements in each release, I wanted to go over a few of the small but useful changes to the personal messenger that you'll find in our next release, 4.1.13. Read/unread filtering The first improvement is that you can now filter the message list by read and unread, making it a little easier to browse through just the messages you're interested in. Search improvements Next up, the messenger search has been improved in a couple of ways; first, you can now also search the names of both the recipients and the senders, and second, we've added a menu so you can specify which fields in particular you want to search by. Easier moving Finally, we've added a popular request - the ability to use the mass-move tool inside the messenger. You can now check multiple messages, and the usual mass-action toolbar will appear that will allow you either move them to another folder, or, has been the case in the past, delete them. While these are each small improvements by themselves, we hope the incremental changes in each release add up to a more pleasant experience for users.
-
Theme Tip: Replacing forum icons with images
In IPS4, it's easy to add custom icons to your forums, simply by uploading them on the Edit Forum screen in the AdminCP. But if you want to replace all of your forum icons, uploading the same icon for each forum can be a bit tedious. It's easy to use some custom CSS to replace all of the icons - lets see how. First, you'll want to upload the image(s) you want to use to the Resources section of your theme so that it can be used in your CSS. To start with, we'll use the same image for both read and unread status, but we'll cover using a different icon for both too. The basics Here's the basic CSS to replace the icon for all forums with your custom image: body[data-pageapp="forums"] .cForumRow .ipsItemStatus.ipsItemStatus_large { width: 50px; height: 50px; border-radius: 0; background-color: transparent; background-image: url('{resource="mushroom.png" app="core" location="front"}'); background-size: 50px 50px; } body[data-pageapp="forums"] .cForumRow .ipsItemStatus.ipsItemStatus_large > i { display: none; } What we're doing here is specifically targeting the item status icons in the forums app, using the body[data-pageapp="forums"] selector. Within this style, we're setting the size of the icon - I've chosen 50px here which is about right in most cases, although you can change this if desired. Next we reset the border radius and background color so the icon looks right. And finally, we set the background image to our icon by using the {resource} tag and the background size to the same dimensions we just set the element to. The next style hides the FontAwesome icon that IPS4 inserts by default, so that our icon can be seen. Using a different 'read' icon By default, your icon will be faded out for 'read' icons, but it's easy to use a completely different icon if you wish. Simply add: body[data-pageapp="forums"] .cForumRow .ipsItemStatus.ipsItemStatus_large.ipsItemStatus_read { background-image: url('{resource="mushroom_faded.png" app="core" location="front"}'); } All we're doing here is using a more specific selector with .ipsItemStatus_read so that only the 'read' state is targeted. In the style, we specify the background image - we don't need to set and reset the other rules again because the styles we wrote in the first step are inherited. Using different icons for redirect or Q&A forums If you want to add icons specifically for redirect or Q&A forums, you can do that by targeting unique classes that are added to the icons for those kinds of forums. Those classes are .cForumIcon_redirect and .cForumIcon_answers, respectively. So, to use a custom icon for a Q&A forum, you would add another style like so: body[data-pageapp="forums"] .cForumRow .cForumIcon_answers.ipsItemStatus.ipsItemStatus_large { background-image: url('{resource="question.png" app="core" location="front"}'); } Notice we've added .cForumIcon_answers to our selector.
-
Theme Tip: 5 useful template tags
IPS4's theme system has a feature called template plugins, which are special tags that do something to the values you pass in. You'll see them throughout the templates - they look like this: {lang="..."} This tag displays the language string for the key you pass into it, and is probably the most commonly used one. But there's many others too, so let's review some of the useful ones you can use in your themes and addons. {member} If you need to show any data about a member, the {member} tag is very useful. It's a shorthand that can display properties and call methods on a member object, so it's much neater than the manual approach. It's used like this: // Get a property, like 'name' {member="name"} // Call a method, like 'link()' {member="link()"} By default, it will work with the currently logged-in member, but you can pass an id attribute to show data about any member: // Show the name of member #67 {member="name" id="67"} {expression} The expression tag allows you insert simple one-line PHP expressions into your templates. For example, if a variable is an array of values and you want to show one per line, instead of writing a loop, you could do: {expression="implode( '<br>', $myArray )"} {prefix} The prefix tag is unusual in that it's designed specifically for use in CSS files. It prefixes CSS styles with the various vendor prefixes, meaning instead of writing: .myClass { -webkit-transform: scale(3) rotate(45deg); -moz-transform: scale(3) rotate(45deg); -o-transform: scale(3) rotate(45deg); transform: scale(3) rotate(45deg); } You can write: .myClass { {prefix="transform" value="scale(3) rotate(45deg)"} } {hextorgb} Continuing with the CSS theme, next there's the "Hex to RGB" tag. If you're a theme designer and want to use a theme setting value but apply some transparency, this tag will be particularly useful to you. Color theme settings are simple hex values, e.g. #000000. To apply some transparency, you need to use the rgba notation however (the 'a' meaning 'alpha channel', otherwise known as transparency). The {hextorgb} tag does this for you. It accepts either a hex color, or a theme setting key. By default it outputs the same color in rgb notation, but if you want to add transparency, you can add an opacity parameter which will represent the alpha channel value. {hextorgb="#ff0000"} --> rgb(255,0,0) {hextorgb="page_background" opacity="0.6"} --> rgba(235,238,242,0.6) {truncate} Finally, there's the truncate tag. This tag takes some text (usually as a variable), and truncates it to the length you specify. By default it appends an ellipsis (...) to the end of the content, although this is configurable via the append parameter. {truncate="$someLongText" length="300"} Note that this isn't designed to be used on HTML markup; you may break your page if HTML tags are included in the text. For those cases, consider using the javascript ipsTruncate widget instead. I hope this overview of 5 lesser-known template tags will help you as you build themes or applications! Share your related tips in the comments.
-
New in 4.1.12: Round up
Last week we introduced you to a couple of key new improvements in IPS Community Suite 4.1.12, the new post preview and enhanced activity streams and search. However, this is a packed release, so I wanted to quickly review what else you can expect to find when it is released this week. Mentions 4.0 introduced mentions, and since then a frequently-requested feature is the ability to ignore notifications triggered by particular members. In 4.1.12, we enhanced the Ignore Users functionality to also allow you to block mention notifications. They will still be able to mention you in posts, but you will no longer be notified about it. Ratings As of 4.1.12, ratings will now display half-stars in order to be more accurate. Users will still rate whole stars out of 5 (or 10 if configured so), but the aggregated ratings displayed alongside content will be more fine-grained. Custom date formatting We have used built-in, automatic locale formats for dates since 4.0, but it became increasingly clear that this did not offer the flexibility that some community administrators desired. As a result, 4.1.12 re-introduces the ability to provide custom formats for dates. Bug fixes Amongst the handful of new features, there's over 400 other bug fixes and improvements that contribute towards the overall stability of the IPS Community Suite, as we start working towards the next major release, IPS Community Suite 4.2 which will be available later this year. Further fixes for stability in the 4.1 line will come before 4.2 is available. Please check our release notes to read more about other smaller changes and fixes in 4.1.12.
-
New in 4.1.12: Improvements to Activity Streams and Search
We are currently beta testing our next release, 4.1.12, which contains hundreds of bug fixes, dozens of improvements, as well as a handful of new features. In this post, I want to cover some improvements we've made to two key areas: activity streams and search. Activity Streams The first improvement we made is to change how the expanded/condensed toggles are displayed to improve their clarity. From studying the feedback from administrators and users, we discovered that many people did not realize the view could be changed. To improve this, the toggles now explicitly say 'Condensed' and 'Expanded', making it much clearer how the view can be toggled to your own preference. More clearly marked expand and condense options for Activity Streams Next, a common point of feedback about Activity Streams is that clicking a result and then hitting the Back button in the browser means you are put back at the first batch of results, losing your place in the stream. In 4.1.12 we improved this so that clicking Back will load the last batch of results you were viewing, enabling you to continue browsing from whence you left off. Finally, in the Content Types menu we added an Apply button. We discovered that users were not always sure how to save the selection of content types they had made (which automatically happened when that menu was closed). To alleviate this, the new Apply button will save the selection and close the menu, updating the stream results in real-time as expected. You can still simply click out of the menu to apply changes as well. The new Apply button in the Content Types menu Search While overall improvements to search (specifically the algorithms to match and return the results) are a matter of ongoing research and refinement which we will improve in the 4.2 series and beyond, 4.1.12 sees one small improvement to the options available to users. While you have always been able to search within a particular forum, category etc. while browsing that area, you were not able to retroactively filter into particular areas after performing a more general search. IPS Community Suite 4.1.12 adds this ability to the interface, allowing you to get more specific results from a particular area of the community. Version 4.1.12 is currently in beta testing and should be released in the next two weeks.
-
New in 4.1.12: Post preview
We are currently beta testing our next release, 4.1.12, which contains hundreds of bug fixes, dozens of improvements, as well as a handful of new features. I wanted to introduce one of those new features: post preview. Long-time users of our software will know that a post preview function was a standard feature, but we took the decision to not include it in the initial IPS4 release. It had a couple of drawbacks: it only applied to certain pages, such as topic view - other WYSIWYG editors simply didn't get a preview the workflow wasn't very good for modern web apps, requiring a round-trip to the server and a full page refresh When IPS4 was released, we felt that the built-in rendering of the editor was a sufficient preview of how the end result would appear. However, while analyzing ongoing customer and user feedback for IPS4 in its first year of release, we have seen that a preview still has a use. There are some circumstances when a true WYSIWYG experience is just not possible such as using more advanced formatting (like LaTeX) or when admins create certain custom editor plugins. As a result, we rethought post preview. We wanted to ensure that all editors could be previewed, and that it didn't have a clunky workflow. In addition, since IPS4 uses a responsive theme, we wanted to give users the opportunity to preview how their post would look on different devices. Here's the result, and what will be available in 4.1.12: Post preview in IPS Community Suite 4.1.12 The preview is shown by clicking a new button on the toolbar (meaning it can be moved, removed, etc. just like the other default buttons). When the preview loads, the toolbar allows the user to resize it to different device sizes. If they are on desktop, they can also view it at tablet at phone sizes; on a tablet, it can also be viewed at phone size. So now we not only show a true preview of what content will look like when posted, but we also allow you to preview how it will look on other devices. Of course that preview is just a best-guess since different devices have different window sizes but it does give you an idea. We hope this reimagining of an old feature for a more modern web will please end-users and make posting content a more accurate process. Stay tuned for more updates on what's included in 4.1.12! Version 4.1.12 is currently in beta testing and should be released in the next two weeks.
-
Theme Tip: Dynamic(ish) forum feeds inside Pages databases
Recently, we had a post in our pre-sales forum that asked how to achieve a few different things with Pages. One of the questions asked was if it was possible to show topics from a particular forum in each database record. While Pages can create a topic for each record for you, there's no way to associate an entire forum with a record. In my reply, I indicate that you'd need to have a forum ID stored with each record in a custom field, and then use PHP to interact with our API to pull the topic list. As it turns out, however, there's an easier way that I discovered after some experimentation. In hindsight it's obvious, but I want to share it here because it could open up some other interesting possibilities with some creative uses. Setting up blocks The first thing we need to do is create our blocks. We're going to create a block for each of our forums. You can set whatever parameters you want here, but the important thing is that they're named consistently using the forum ID. So, for my forum ID 2, I've named the block forum_2. This will allow us to include our blocks later. Creating one of the blocks we'll need Adding the field Next we'll need to create a field in our Pages database that will be used to set the forum ID that is going to show in each record. For simplicity, I'm creating a Number field and I'll enter the forum ID manually, but if you wanted to go further, you could create a Select Box field, with the key being each forum and the value being the name. This would give you a friendlier input from which to select the forum for each record. Here, though, I've just created the Number field, and named it Forum ID. Setting up the database field Using the field formatter to show the correct block Finally, we'll use the Field Formatting options to show the correct block based on the forum ID entered for each record. On the Display Options tab, I'm going to hide the field from the listing template, but show it on the display template. I've selected Custom as the format, then entered this format: {{if $formValue}} {block="forum_{$formValue}"} {{endif}} That's it - that's all you need for this to work. It's very simple. All we're doing is passing the $formValue of the field (which is the raw value) into the {block} tag as a variable, so that the block that is rendered depends on this value. As long as a block exists with the correct key, it'll be shown in the display view: End result, with the correct block pulled in based on the ID we provided to the record Going further So, given that we know we can use variables in block names to pull in different content (providing the block has been created ahead of time), what other possibilities are there? For starters, we aren't just restricted to using field formatters. Instead, we could use blocks directly in the database templates, using some of the data available there. Here's one idea - if you have just a few staff members posting records, you could create a block for each staff member that lists their recent posts, status updates, etc. In your database template, you could include the correct block by doing this: {block="content_for_{$record->author()->member_id}"} I hope this relatively simple approach gives you some ideas for more creative ways to use blocks. If you have any suggestions for other ways to use this approach, please let us know in the comments!
-
Theme Tip: Styling specific elements on specific pages
Occasionally you'll want to style a specific element on a specific page of your community - maybe you want to change how topic titles are shown inside a topic, or do something specific to the styles used in activity streams, without also altering other screens where the same elements are used. Your first instinct might be to open the template editor and add some custom classnames so you can style them. This would certainly work, but the downside is your template is now customized, so any future IPS4 updates would leave the template out of date. Not ideal by any means. Instead, you can use some helpful attributes that IPS4 adds to the body element, and then build a CSS selector around them. There's four attributes, and they always reference the current page the user is on: data-pageApp - The application key (e.g. core, forums, cms etc.) data-pageModule - The current module with the application (e.g. pages) data-pageController - The current controller within the module (e.g. topic, page etc.) data-pageLocation - Either admin or front. So let's say we want to change how the .ipsPageHeader element looks within topic view. Our selector would look like this: body[data-pageapp="forums"][data-pagemodule="forums"][data-pagecontroller="topic"] .ipsPageHeader { ...your styles } If you don't want to be that specific, you can just use the attributes you need. For example, if you want to change all .ipsPageHeader styles in the Forums app, you'd do: body[data-pageapp="forums"] .ipsPageHeader { ...your styles } Tip: If you don't know the correct app/module/controller for the page you're on, you can find out by visiting the page and then viewing the page source. You'll see these attributes in the body tag near the top. And as always, be sure you add your CSS to custom.css to keep your upgrades easy This theme tip is taken from our guides section.
-
Theme Tip: Using custom template bits
We frequently encourage people to use custom CSS files when designing their themes. The reason for this is simple: it makes upgrading your site much easier because IPS4 can apply any changes to its own CSS files, and will leave your custom CSS files untouched. If instead you made edits to IPS4's CSS directly, it wouldn't be able to upgrade them automatically, which means more work for you, and a potentially broken UI on each upgrade. Something that's not quite as common, but that we still strongly suggest, is using custom template bits as much as possible. The most common template you'd edit is globalTemplate, perhaps to include some extra resources in the <head>, a custom header, and maybe some footer pieces. The usual approach would be to simply add all of that custom HTML directly into globalTemplate, but my recommendation is that you instead create each piece as a custom template bit, and then include it. With templates, it's not quite as much of a clear-cut benefit as with CSS; you'll still need to modify the original template in order to include your custom pieces of course. But there's still good reasons for doing so; it keeps your template as clean as possible, meaning if in a later upgrade you have to revert it to get the latest changes, reapplying your custom pieces is easy - you just add the template includes back in. We've been taking this approach with all custom themes we've created since IPS4's release (dozens by my last count). We try and keep the naming convention consistent too. All custom templates are named _customABC.phtml and exist in the /front/global/ group in the core application. This puts them in an easy-to-find location, and because of the underscore prefix, they're shown at the top of the directory. Example custom template bits in a custom theme Using them is simple: {template="_customHeader" group="global" app="core"} I hope this approach helps you keep your templates clean and more manageable! If you have any tips for working with your templates, please share them in the comments!
-
Theme Tip: Advanced uses for Pages database fields
Our Pages app includes a powerful feature that allows you to create your own databases within the community. Within each database, you create custom fields (we support a number of custom types, from plain text fields, to YouTube embeds and more). And while we provide some generic, simple templates to display your data, custom templates allow you to more precisely control how your database looks in a manner best suited to your site. Anyone who has created a Pages database will be familiar with using custom fields. You may have created a field for the title of your item, or an upload field so that the item contains a file for users to download. But beyond these straightforward uses, I wanted to explore some more advanced uses of custom fields. Fields don't necessarily have to be displayed to the user - or at least not in the usual way. We can use them as configuration options for our record display, or manipulate the data in order to show it in a different way. Let's take a look at some examples. 1. Adding an optional badge to records We'll start with a fairly simple example. In our Guides section, we highlight guides that have a video tutorial by showing an 'Includes Video Guide' label on the listing: We achieve this simply by having a Yes/No field that we turn on as needed. In the field format, we turn the Yes/No value into the label by setting the format to Custom and using this code: {{if $formValue == 1}} <span class='ipsType_medium'><i class='fa fa-video-camera'></i> <strong>Includes Video Guide</strong></span> {{endif}} 2. Using fields as a way to configure the record display Fields don't necessarily need to be shown to users. Instead, we can use them as a means to configure the record display, giving us some really powerful flexibility in how we show records. In this contrived example, I'm going to create a field that changes the background color of the content. Create a Select Box field. Each option key will be a hex color, while the value will be the name the record creator will choose. Set the field key to record_background Set the field formatting to Custom, and the format to simply: {$formValue}. This means it will output our hex value instead of the color name. In the display template assigned to this database for records, we can use the field like so: <div style='background-color: #{$record->customFieldDisplayByKey('record_background', 'listing')|raw}' class='ipsPad'> ...rest of the template... </div> Now, when you create a record, you can choose a color and that color will be used when the record is shown: You can use this approach in others ways - toggles to control the layout of the record, or options for grid sizes, or even take an upload field for images and set the background of an element as that image. 3. Pass data to 3rd-party integrations Pages has built-in support for several 3rd party integrations, such as Spotify, Soundcloud, YouTube and Google Maps. But using custom fields, you can pass data to other services too. Let's say we wanted to embed an iTunes album widget into each of our records - perhaps the album is relevant to the Pages record in some way and we hope to encourage some click-throughs. In this example, we'll use the embed.ly service. Create a URL custom field. Set the field key to itunes_album Set the field formatting to Custom, and the format to: <a class="embedly-card" href="{$formValue}">iTunes Album</a> <script async src="//cdn.embedly.com/widgets/platform.js" charset="UTF-8"></script> In your database display template, position the field as desired by adding: {$record->customFieldDisplayByKey('itunes_album', 'listing')|raw} Now when you add an iTunes album link to your record, you'll get an embed automatically! This approach is great for a range of uses. Perhaps you have an Amazon Associates account and want to add a relevant product link to each of your records so that you earn a commission when users click through. Using database fields and templates in this way, it's easy to set up. I hope that's given you some ideas of other ways you might use database fields in Pages. Share any interesting uses you've come up with in the comments!
-
Support for PHP 5.4 ending soon
For our self-hosted customers, we wanted to give you advanced notice that support for PHP 5.4 in the IPS Community Suite will be ending soon. IPS Community Suite 4.1.11 will be the last release to support this version of PHP. PHP 5.4 was released in 2012 and reached 'end of life' in September 2015, and so we will be requiring at least PHP 5.5 from IPS Community Suite 4.1.12 onwards. We do recommend PHP 5.6 or greater as 5.5 is approaching end of life as well. If you currently use PHP 5.4, please contact your host and ask them to upgrade to a supported version as soon as possible. If you would rather not have to worry about server-level issues like this, consider switching to one of our Community in the Cloud plans. They include all of our suite apps and we take care of all of the server management for you, leaving you to focus on running your community. If you are currently self-hosting, we can transfer your community to a cloud plan for free, in most cases. Contact our sales team for more information.
-
Theme Tip: Using Pages blocks anywhere
Blocks are an extremely popular feature in IPS4, used by a huge number of customers to great effect. They range from feeds of topics, to statistics, to custom blocks that can contain anything you wish. They're a great way to add dynamic content to your community theme. What many people don't know is that blocks you create with Pages can be used anywhere in your theme, not just in the designated block containers (in the header, footer & sidebar). The {block} tag It's really easy to do so. Here's the tag you'd use: {block="block_key"} That's it! The block_key is the one you specify when you're creating the block in Pages (if you don't specify one manually, Pages will auto-generate one for you). Where can you use them? Block tags can be used anywhere that template logic is supported. That includes: Theme templates Pages page content Other kinds of templates (e.g. database templates) Even within other blocks! What can you do with them? The obvious benefit of blocks is that they are reusable, so in any situation where you need the same content duplicated, it makes sense to put the content in a custom block instead, and simply insert it wherever needed. Then if you need to update the content later, you have one place to do so. Custom menus are a great example of reusing blocks; since blocks have full use of template logic, you can build your menu HTML in a block, use HTML Logic to highlight the correct item, and insert the menu block on each of your pages. We use this approach on our feature tour section menu. Here's a snippet of the menu block HTML for that page: <nav id='elTourNav'> <div class='container'> <ul class='ipsList_inline'> <li><a href='/features/apps' {{if \IPS\Request::i()->path == 'features/apps'}}class='sSelected'{{endif}}>Our Apps</a></li> <li><a href='/features/engagement' {{if \IPS\Request::i()->path == 'features/engagement'}}class='sSelected'{{endif}}>Engagement</a></li> <!-- ... --> </ul> </div> </nav> Blocks are useful beyond that, though. A couple of weeks ago, we showed you how to use HTML Logic to only show content to certain groups. Using blocks is actually an easier way to do this - simply add the content to a custom block, then check the groups who should see it. We use this technique to show a 'welcome to our community' message to guests on our own community. We created our welcome message as a custom Pages block, set it so that only guests have permission to view it, and then added it to our template header. Simple, effective and easy to manage. That's just two ways you can use blocks - there's many other creative users too! If you've used blocks in an interesting way, share your example in the comments!
-
7 ways to secure your community
Security should never be an afterthought for your community. All too often, site owners consider beefing up their security only when it's too late and their community has already been compromised. Taking some time now to check and improve the security of your community and server could pay dividends by eliminating the cost and hassle of falling victim to hacking in the first place. Let's run down 7 ways that you can protect your community with the IPS Community Suite, from security features you may not know about to best practices all communities should be following. 1. Be selective when adding administrators Administrator permissions can be extremely damaging in the wrong hands, and granting administrator powers should only be done with great consideration. Granting access to the AdminCP is like handing someone the keys to your house, so before doing so, be sure you really trust the person and that their role requires access to the AdminCP (for example, would moderator permissions be sufficient for the new staff member?). Don't forget to remove administrator access promptly when necessary too, such as the member of staff leaving your organization. Always be aware of exactly who has administrator access at any given time, and review regularly. You can list all accounts that have AdminCP access by clicking the List Administrators button on the System -> Security page. 2. Utilize Admin Restrictions In many organizations, staff roles within the community reflect real-world roles - designers need access to templates, accounting needs access to billing, and so forth. IPS4 allows you to limit administrator access to very specific areas of the AdminCP with the Admin Restrictions feature, and even limit what can be done within those areas. This is a great approach for limiting risk to your data; by giving staff members access to only the areas they need to perform their duties, you reduce the potential impact should their account become compromised in future. 3. Choose good passwords This seems like an obvious suggestion, but surveys regularly show that people choose passwords that are simply too easy to guess or brute force. Your password is naturally the most basic protection of your AdminCP there is, so making sure you're using a good password is essential. We recommend using a password manager application such as 1password or LastPass. These applications generate strong, random passwords for each site you use, and store them so that you don't have to remember them. Even if you don't use a password manager, make sure the passwords you use for your community are unique and never used for others sites too. 4. Stay up to date It's a fact of software development that from time to time new security issues are reported and promptly fixed. But if you're running several versions behind, once security issues are made public through responsible disclosure, malicious users can exploit those weaknesses in your community. When we release new updates - especially if they're marked as a security release in our release notes - be sure to update as promptly as you can so you receive the latest fixes. Your AdminCP will also let you know when a new version is ready for download. 5. Use .htaccess protection for your AdminCP In addition to IPS4's own AdminCP login page, you can set up browser-level authentication, giving you a double layer of protection. This is done via a special .htaccess file which instructs the server to prompt for authentication before access to the page is granted. IPS4 can automatically generate this file for you - simply go to System -> Security in your AdminCP, and enable the "Add a secondary admin password" rule. And it should go without saying, but to be clear: don't use the same username or password for both your .htaccess login and your admin account, or the measure is redundant! 6. Restrict your AdminCP to an IP range where possible If your organization has a static IP or requires staff members to use a VPN, you can add an additional layer of security to your community by prohibiting access to the AdminCP unless the user's IP matches your whitelist. This is a server-level feature, so consult your IT team or host to find out how to set it up in your particular environment. If you're a Community in the Cloud customer, contact our support team if you'd like to set up this protection for your account. 7. Properly secure your PHP installation Many of PHP's built-in functions can leave a server vulnerable to high-impact exploits, and yet many of these functions aren't needed by the vast majority of PHP applications you might run. We therefore recommend that you explicitly disable these functions using PHP's disable_functions configuration setting. Here's our recommended configuration, although you or your host may need to tweak the list depending on your exact needs: disable_functions = escapeshellarg,escapeshellcmd,exec,ini_alter,parse_ini_file,passthru,pcntl_exec,popen,proc_close,proc_get_status,proc_nice,proc_open,proc_terminate,show_source,shell_exec,symlink,system Another critical PHP configuration setting you need to check is that open_basedir is enabled, especially if you're hosted on a server that also hosts other websites (known as shared hosting). If another account on the server is comprised and open_basedir is disabled, the attacker can potentially gain access to your files too. Naturally, Community in the Cloud customers needn't worry about either of these steps - we've already handled it for you! So there we go - a brief overview of 7 common-sense ways you can better protect your community and its users. As software developers, we're constantly working to improve the behind-the-scenes security of our software, but as an administrator, there's also a number of steps you should take to keep your community safe on the web. If you have any tips related to security, be sure to share them in the comments!
-
Theme Tip: Create custom error pages with the Pages app
When IPS4 encounters an error (be it a simple 404 Not Found or a more complex configuration issue), the user sees a standard built-in error page. That's fine in many cases, but did you know you can create your own error page using our Pages app? This is a particularly good approach for communities that use Pages for their website too. If you have built a website theme, the standard error page may not fit with your visual style, so building your own error page allows you to improve it. You might want to show some helpful links to other parts of your website, for example. Creating your error page The first step is creating your error page in Pages. Note that for this page, you must create a manual page - the Page Builder tool can't be used in this case. In order to show the error on your page, there's two special tags you should insert in the page content. When your page is shown in response to an error, Pages will swap out these tags for the relevant text. They are: {error_code} Replaced with the technical error code for this error. This code identifies the exact piece of code that triggered the error, and can be given to IPS support technicians to help diagnose problems. {error_message} Replaced with a human-friendly description of the error that occurred. Configuring Pages to use the error page Next, set Pages to display the error page. You do this in the Pages section; click the Advanced Settings button, and select your page from the list. Note that this will replace all error pages across the suite - not just errors triggered by Pages itself! Have a request for a theme tip? Let us know in the comments and we'll try and help out in a future tip!
-
Theme Tip: Use HTML logic to display content to specific groups
HTML Logic is our name for the additional tags available in IPS4's templates that allow runtime logic to be executed. It comprises if/then/else statements as well as loops and more. Since HTML Logic has access to all of the underlying PHP framework in IPS4, it's very powerful and a lot can be achieved with it. One common use is to limit certain content within a template to particular member groups. Let's see how that might be done. Showing or hiding content only to guests We'll first look at a simpler idea: showing or hiding content specifically to guests (i.e. anyone who isn't logged in). Within IPS4, the \IPS\Member::loggedIn() object contains information about the current user. Guests always have a member_id of NULL (i.e. no value), so we can simply check that value in our logic tag: {{if \IPS\Member::loggedIn()->member_id === NULL}} This content *only* shows to guests, since they have a NULL member_id. {{endif}} {{if \IPS\Member::loggedIn()->member_id}} This content *only* shows to logged-in users since their member_id is a number, which will equal true. {{endif}} Showing content only to specific groups Let's go a bit further and this time show content to specific (primary) member groups. First, you need to get the IDs for the group(s) you want to deal with. You can find this by editing the group in the AdminCP, and making a note of the id parameter in the URL. On my installation, the Administrator group is ID 4 so we'll use that in our example. Once again, we're using the \IPS\Member::loggedIn() object, but this time we're using the member_group_id property. {{if \IPS\Member::loggedIn()->member_group_id === 4}} This content only shows to members in the "Administrators" group (ID 4 in our example) {{endif}} Working with multiple groups at once Following the code above, you could simply repeat the check against \IPS\Member::loggedIn()->member_group_id several times, for each ID you want to allow. However, since our templates allow arbitrary PHP expressions to be used, there's a neater way: use an array of member group IDs you want to allow, and check against that using PHP's in_array function. Here's an example where we only show content to group IDs 2, 4 and 6: {{if in_array( \IPS\Member::loggedIn()->member_group_id, array( 2, 4, 6 ) )}} This content only shows to members in groups with the ID 2, 4 or 6. {{endif}} Have a request for a theme tip? Let us know in the comments and we'll try and help out in a future tip!