-
Posts
24,413 -
Joined
-
Last visited
-
Days Won
84
Content Type
Downloads
Release Notes
IPS4 Guides
IPS4 Developer Documentation
Invision Community Blog
Development Blog
Deprecation Tracker
Providers Directory
Projects
Release Notes v5
Invision Community 5 Bug Tracker
Forums
Events
Store
Gallery
Everything posted by Rikki
-
In my opinion, to do a PWA well, you need to do more than just take a responsive theme and add a manifest. PWAs are expected to feel like native apps, and so we'd have quite a bit of work to do to meet that standard I think. We aren't ignoring mobile though, don't worry ?
-
We don't plan to switch to FA5 for the time being. It'll be something we consider for the next major update.
-
Making security considerations a key part of your community setup and maintenance can save you from many future headaches. You've worked hard to get your community moving. Don't make yourself an easy target and undo that work. Here’s our current advice to our customers. 1. Enable HTTPS HTTPS is fast becoming the standard way to serve websites. In 2016, more than 50% of web requests were served under HTTPS for the first time. Chrome and Firefox now explicitly warn users on login forms that aren’t sending data over HTTPS, and it’s not hard to imagine that in the near future all insecure pages will receive the warning. HTTPS simply means that website data is served over a secure connection and can’t be read or tampered with by a ‘middle man’ hacker. You can identify a site using HTTPS because the address in your browser will show ‘https://’ (instead of http://), and normally a lock icon or the word ‘secure’. Invision Community supports HTTPS by default simply by changing your base URL configuration to include HTTPS. Of course your web host will need to support it as well and our Invision Community Cloud services support it by default. Contact support if you have any questions. Recommendation: Set up HTTPS for your entire community to prevent ‘man in the middle’ attacks. 2. Set up Two Factor Authentication Invision Community supports Two Factor Authentication (2FA for short), and we highly recommend making use of this feature for your users, but especially for your administrator staff. 2FA is a system that requires both a user’s password and a special code (displayed by a phone app) that changes every few seconds. The idea is simple: if a user’s password is somehow compromised, a hacker still wouldn’t be able to log in to the account because they would not have the current code number. You may already be familiar with 2FA from other services you use. Apple’s iCloud, Facebook and Google all offer it, as do thousands of banks and other security-conscious businesses. Invision Community supports 2FA via the Google Authenticator app (available for iOS and Android) or the Authy service, which is able to send codes to users via text message or phone call. You can also fall back to security questions instead of codes. You can configure which members groups can use 2FA, as well as requiring certain groups to use it. Recommendation: Require any staff with access to the Admin Control Panel or moderation functions to use 2FA, to ensure that no damage can be done should their account passwords be discovered. Allow members to use 2FA at their discretion. 3. Configure password requirements The password strength feature displays a strength meter to users as they type a new password, showing them approximately how secure it is, as well as some tips for choosing a good password. While you can leave this feature as a simple recommendation for users, it’s also possible to require them to choose a password that reaches to a certain strength on the meter. Recommendation: Require users to choose at least a ‘Strong’ password. 4. Use Admin restrictions It’s very common that many different staff members need access to the Admin Control Panel depending on the role. You may have design staff, billing staff, community managers, and so on, all with particular tasks they would like to achieve. Invision Community can help improve the security of your Admin Control Panel by allowing you to restrict the functions available to each administrator, granting them access to only the tools needed to do their job. Recommendation: Audit your community’s administrator accounts and applying restrictions where it makes sense to do so. 5. Stay up to date It’s important to ensure you’re always running the latest release of Invision Community. With each release, we add new security features, audit code and fix any issues reported through responsible disclosure. Falling behind can therefore make your community a tempting target for potential hackers. Your Invision Community Admin Control Panel will let you know when a new release is available, and you can also check out our Release page to track releases. For our Enterprise customers, we’ll automatically apply updates for you shortly after release as part of your plan. For our self-hosted and Cloud customers, you can easily apply new updates via the Admin Control Panel with a couple of clicks. Our Invision Community Cloud contains all best practices for security. However, if you are self-hosted, be sure to work with your web host to ensure your server is setup properly. Ensuring that server software, firewalls, and access controls are in place is very important as an insecure server can be your worst enemy. Recommendation: Aim to install latest updates as soon as feasible. 6. IP address restrictions For organizations where staff are centrally-based in one location, or are required to use a VPN, you can improve your community security by restricting access to the Admin Control Panel to the IP addresses your staff will be using. This is a server-level feature, so contact your IT team to have this facility set up your installation. Enterprise customers who wish to utilize IP restrictions should contact our Managed Support team, while Cloud customers can submit a support ticket to have this set up. Recommendation: Where staff all access the community from a small number of IP addresses, restrict Admin Control Panel access to those IPs. Summary Don’t leave security as an afterthought. Invision Community includes a range of tools to help you ensure your data and members protected, as well as industry-standard protections ‘under the hood’. Make use of these features, and they’ll help ensure the wellbeing of your site. As always, if you have any questions or need advice, our support team are on hand to assist you.
-
Unlike a regular website, where you write content for each page, target keywords and optimize text, a forum community's content is predominantly written by users. They don't know or care about your site's SEO and just want to interact with other users or find answers to their questions. To keep your community moving forward, Invision Community implements many best-practice SEO techniques and approaches for you automatically, without you needing to lift a finger. Even still, there are a few additional steps you can take to potentially help your site rank better. How Invision Community helps you automatically Invision Community does a lot of automatic SEO for you behind the scenes to help your site rank better or to help search engines understand your content. Some of those include: Sitemap generation A sitemap file helps search engines to locate pages within your site. This helps search engines find pages so they will be crawled quicker. Invision Community automatically generates a sitemap for you that points to all of your content URLs, and submits it to Google. JSON-LD Another way a site can help search engines is by providing metadata about a page. For example, if the page contains a review, additional data can be supplied to the search engine with rating count, average, and so on. There are dozens of items that can be described in this way, and doing so can mean your results in search engines display this additional data. This makes results more useful to users, potentially leading them to click on your result versus another. It can also help search engines understand your content better. Canonical URLs Search engines can penalize your site in situations where the same content can have multiple URLs. With software that generates pages dynamically, such as a community, this can happen frequently because there are URLs to get the last read post, the latest post, the first post and so on, all ultimately pointing to the same topic page. Invision Community takes care of this for you by setting a canonical URL for every page, telling the search engine which is the definitive URL it should use. Semantic markup The HTML markup used to generate a page is possibly the most important factor impacting SEO. Each HTML tag has a specific meaning (e.g. H1 is an important title) and allows search engines to determine the structure of the page. It's therefore important that tags are used correctly and in the appropriate context - known as semantic markup. Invision Community has been built with semantic markup principles in mind right from the start. Responsive theme Google has been transitioning to a mobile-first approach when crawling sites and it's likely this does or will factor into its PageRank system. Now more than ever it is important that your community offers a genuine mobile experience. Invision Community achieves this by supporting responsiveness - where the theme adapts depending on size of the screen being used - by default. What you can do to improve ranking Let search engines see your content One of the most important things you can do to help with SEO might seem obvious, but we've seen many people unwittingly neglect it: ensure that search engines can see your content! It's tempting to lock down your community so that users have to log in before being able to see your content, and for some communities this might be necessary. However, a search engine can only see content accessible to guests, and so by locking your community down a search engine won't be able to see very much at all, and your pages won't show in search results. Wherever possible, we suggest allowing guests to read your content, though you can require registration to reply. Enable HTTPS Even ignoring SEO this is a good idea, because it's more secure for your users and browsers are increasingly alerting users about sites that don't use HTTPS, showing them as insecure. In terms of SEO, research has shown a correlation between between sites using HTTPS and their ranking position, and in 2014 Google indicated that HTTPS would be a “ranking signal” going forward. Given the other benefits of HTTPS, it would therefore be wise to enable it across your community. Ensure your site loads fast A fast-loading site is very important for rankings, and so you should do what you can to keep your community running quickly. This includes: Enable guest caching Invision Community includes a built-in caching system for pages viewed by guests, ensuring they don't have to be re-generated for every page view. This can greatly speed up your site for guest users and therefore search engines. This is automatically configured on our Cloud services. Don't go overboard with plugins A few good plugins can set your community apart from others, but going overboard can significantly slow down your load times or clutter your interface. Be wary of image-heavy themes As with plugins, a great theme is a good thing to have, but try to avoid one with extensive use of very large images. Choose a good host Some website hosts are slower than others, so ensuring your host is up to scratch is important. Of course our Cloud services are a great solution here! Use 301 Redirects if migrating If you're migrating from another community platform, your page URLs will change to reflect Invision Community's architecture. You can greatly improve SEO retention by using special redirects (known as 301 Redirects) to send users from your old URLs to the new. Search engines understand this method and will update their records. We include redirects in our free migration packages to help you retain your SEO standings after migrating to Invision Community. Write relevant content If your site targets a particular niche, you may see benefit in writing longer-form content as articles on a site blog. This kind of content ranks well and allows you to ensure keywords are used (versus content posted by members, which can be anything). You can also encourage further discussion of the article in the wider community, amplifying its benefit. For a site news page/blog, our Pages app can be used to build an articles section for this purpose. Use social media profiles to your benefit You should register social media profiles for your site on the popular platforms and make them a part of your presence. These sites rank very highly of course, and so if your social profiles can also rank highly for your name, they can be a good way of directing traffic to your site. Use the ‘About' section of the profile to write an interesting blurb about what your site offers. Create eye-catching header images and profile photos to use on the profiles too. Cross-link each social profile to the others (and back to your site, of course). Finally, link to your social profiles from your site too. Invision Community allows you to easily do this and insert icons in your header or footer. Beyond that, you can also use social media to your advantage by cross-linking some of your best content to it. We'll go into more detail on how best to leverage social media in a future article, but the new Promote functionality in Invision Community is a great way of achieving this. Summing Up As always, content is king when it comes to ranking, and that should be your most important focus. Fostering a vibrant community that creates and shares interesting content is key. You can then use SEO methods boosted by Invision Community features to expand your community's reach in search engines. If you have any SEO tips that have helped your site, we'd love to hear them. Share them in the comments below!
-
6 reasons why you shouldn't just settle for a Facebook group community
Rikki posted a blog entry in Community Management
Whether you run an existing community or are taking tentative first steps into setting up an online community forum around your brand, an important choice you need to make is between social networks like Facebook or having a community you own and control. Let's take a look at the benefits of an owned community versus a Facebook group - as well as how you can still use Facebook (and other social media platforms) to your advantage. You own your data The biggest point to consider when using Facebook groups is that you do not own your own data. Facebook owns it and does not even allow you direct access to it. If you decide later to move to a different platform, need to run reports to extract meaningful insights, or otherwise work with your community data: you are out of luck. In contrast, with an Invision Community, your data is your data. You can use it in any way that makes sense for your goals; be it analyzing trends, sending promotions to users, or generating reports and statistics. We never hold your data hostage and there's no fee to get it. Beyond owning the data, you also control how it's used and presented. Facebook is notorious for changing algorithms for when (or even if) people see your posts. When you run your own community the experience for your and your users is in your control. Branding opportunities This is a big one. An owned community gives you the tools you need to make your community a seamless part of your user's interaction with your business. This naturally includes your brand styles (your logo, colors, site navigation and so on) but also your community web address (URL). With an owned community, your URL will be easy to find - customers normally opt for something like forum.yourname.com or community.yourname.com. Users will have more confidence that they're in the right place, and more closely associate your community and your message with your brand. Emails sent out by your owned community can also carry your branding, consistently reinforcing that connection between your business and your community. And, of course, when users share content from your community to Facebook and other social networks, they're sending users directly to your website where you have the opportunity to lead with your most important call to actions. More control over user experience All Facebook groups are, essentially, the same experience and yet your business needs almost certainly aren't the same as every other. One size doesn't necessarily fit all when it comes to community! When you control your own community, you have the ability to control your user's experience. Need to show specific types of data in specific places? You can do that (and more) with Invision Community's easy to use Blocks feature. Need to create a custom community application to serve as a resource center for product support? You can do that too. Another huge benefit of this control is that, unlike a Facebook Group, users won't be seeing ads and 'recommended content' from competing businesses and communities. With user attention being pulled in so many directions these days, the last thing your community needs is for users to leave because Facebook has suggested a competitor! No barriers to monetization Not all communities require a monetization strategy. In many cases, the community is part of a larger customer relationship strategy rather than a revenue-generating destination in its own right. But for those communities that do plan to monetize, options with a Facebook group are at best difficult to act upon, and at worst practically non-existent. In contrast, Invision Community gives you the opportunity to explore monetization strategies that work for you. These might include paid subscription plans (a particularly attractive option for fan club communities), traditional advertising through Google AdSense and other networks, or sponsorship deals with other businesses that might be relevant to your members. Invision Community has tools for each of these approaches built in, allowing you to start monetizing with minimum fuss. Fine-grained permission controls Facebook groups struggle to reflect the real-world roles that staff members play in your organization, limiting your choices to 'administrator' or 'moderator'. And the same is true of users, too - your options for recognizing different levels of user (such as VIPs, or brand ambassadors) are limited. Invision Community is different. Since you are creating and configuring each member group, you can precisely control who can see what, and how they are recognized within the community. You can even sync these roles via Single Sign-On (SSO) making setup and assigning users to groups painless. For staff groups, you can limit access to key community functions based on roles or responsibilities, ensuring access is granted on an as-needed basis only. For users, you can get creative and find a group structure that works best for your specific needs. For example, support communities often find that recognizing the most knowledgeable and helpful members with a new member group (complete with elevated permissions) is a great way of engaging users. And finally, with this control over access, it's very easy to create restricted areas of the community. Whether you want to create a private subforum that staff can use to coordinate tasks or a file repository that's only available to subscribers, Invision Community can achieve it. You can still reap the Facebook benefits Setting up your community within Facebook's walls might not be the best approach for you. That doesn't mean you should ignore Facebook, however. On the contrary, it's an influential platform and there's a very good chance your users are already using it. Invision Community offers a number of tools that allow you to benefit from Facebook while avoiding the drawbacks we discussed. We'll go into more detail on utilizing social media in a future article, but to summarize: Invision Community features social sign-in options, enabling users to register and log in using their existing social media accounts, substantially reducing onboarding friction. Content can promoted by staff back to your social network pages, automatically and on a schedule you decide. Invision Community supports automatic embedding of a wide number of social networks (and other services), allowing users to share their favorite Facebook and Twitter posts and spark a whole new conversation - but this time in your community. Summary When you are creating an online community for your business or hobby it is important to think about your goals and future growth by choosing a platform that is there to work for your needs. When you establish your community on Facebook, you're helping to grow someone else's business (including, potentially, your competitors!) and hoping that some of those spoils fall to you. With an owned community, the rewards of your hard work belong to you and your business alone. Invision Community has been enabling users and businesses to communicate online since 2002, and we're proud of our reputation as a platform that puts control in your hands. Contact us if you'd like to discuss how we can help you too. -
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.
-
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!
-
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!
-
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.
-
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 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.
-
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}} .
-
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!
-
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
-
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!
-
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.
-
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.
-
As with comments, how you display reviews in your application is up to you. However, there are some attributes that your markup should contain in order for dynamic functionality to work correctly. Here's a skeleton you can use as a starting point. <div data-controller='core.front.core.commentFeed' data-feedID='file-{$item->id}-reviews'> {{if $item->canReview()}} <h2 class='ipsType_sectionTitle'>{lang="write_a_review"}</h2> <br> {{endif}} <div class="ipsClearfix"> {{if $item->reviewPageCount() > 1}} <div class="ipsPos_left"> {$item->reviewPagination( array( 'tab', 'sort' ) )|raw} <div class='ipsAreaBackground_light ipsPad'> {$item->reviewForm()|raw} </div> </div> {{endif}} <div class="ipsButtonBar ipsClearfix ipsResponsive_showDesktop ipsPos_right"> <ul class="ipsButtonRow ipsPos_left ipsClearfix"> <li data-action="tableFilter" data-filter=""> <a href="{$item->url()->setQueryString( array( 'tab' => 'reviews', 'page' => 1, 'sort' => 'helpful' ) )}" class="{{if !isset( request.sort ) or request.sort != 'newest'}}ipsButtonRow_active{{endif}}" data-action="filterClick">{lang="most_helpful"}</a> </li> <li data-action="tableFilter" data-filter="members_filter_banned"> <a href="{$item->url()->setQueryString( array( 'tab' => 'reviews', 'page' => 1, 'sort' => 'newest' ) )}" class="{{if isset( request.sort ) and request.sort == 'newest'}}ipsButtonRow_active{{endif}}" data-action="filterClick">{lang="newest"}</a> </li> </ul> </div> </div> <br><br> <div data-role='commentFeed'> {{foreach $item->reviews() as $review}} {$review->html()|raw} {{endforeach}} </div> </div>
-
How to implement reviews Instead of extending \IPS\Content\Comment, your model should extend \IPS\Content\Review (which itself extends \IPS\Content\Comment but adds additional functionality specific to reviews). class _YourClass extends \IPS\Content\Reviews { //... } There are a number of additional keys you need to add to your model's $databaseColumnMap. Each value should be the database column name in your table that holds the value for each property. rating Required. The rating value submitted with the review. votes_total Required. The total number of helpful/unhelpful votes received. votes_helpful Required. The number of votes that indicated the review was helpful. votes_data Required. A JSON object containing details about who has voted helpful/unhelpful (as well as what their vote was). Changes required to the content item model You'll also need to make changes to the content item model. For comments you added a $commentClass property to the model, but for reviews this is named $reviewClass: public static $reviewClass = 'IPS\yourapp\YourClass'; You'll also need to add elements to the content item model's $databaseColumnMap. Below, we show the key you used for comments, and how it differs in name for reviews. Note that if your applications uses both comments and reviews, you should add both the comment and review keys to the column map. num_comments becomes num_reviews last_comment becomes last_review last_comment_by becomes last_review_by unapproved_comments becomes unapproved_reviews In addition, some model properties and methods have different names to reflect their use with reviews. As above, if your application uses both comments and reviews, you should declare/implement both types. Consult the comments documentation for implementation details; aside from the property/method name, the implementation is identical. static $commentsPerPage becomes static $reviewsPerPage commentPageCount() becomes reviewPageCount() commentPagination() becomes reviewPagination() comments() becomes reviews() commentForm() becomes reviewForm() lastCommentPageUrl() becomes lastReviewPageUrl() canComment() becomes canReview() moderateNewComments() becomes moderateNewReviews() canViewHiddenComments() becomes canViewHiddenReviews() There is one additional method available to the content item model that is present only when reviews are used: integer averageReviewRating() Returns the average rating for all reviews on the item.
-
Reviews are almost identical to comments; they behave in the same way and all of the options available to comments are available to reviews too. There's a few key differences: When submitting a review, in addition to the usual text body, members will provide rating out of 5 (or 10 if the site is configured so) Other members will be able to indicate whether they found the review useful or not, and this count is shown below the review. Members will only be able to submit one review per content item. Follow the Comments guide for an overview on implementation details; we won't duplicate them here. The remaining parts of this guide will cover the differences in implementation necessary for reviews.
-
An application within IPS4 is made up of several types of class, and you'll use most of them in your own applications. The structure of your application files is well defined (it's this structure that allows classes to be autoloaded when needed. Structure overview Within your application directory, here's the structure and what each directory contains (some optional directories are omitted here). We'll examine the key parts shortly. /Application.php Your main application bootstrap file. /api Contains REST API endpoints if the application supports the REST API. /data Holds numerous json files that configure your application settings, schema and more, typically used on installation. /dev Only exists when you are in developer mode. /css Contains CSS files for front/admin locations /email Contains templates for notification emails sent by your application /html Contains all of the HTML templates for the front/admin locations that your application will use /js Contains the javascript controllers and templates for the front/admin locations that your application will use. /resources Contains other kinds of resources (e.g. images, fonts, sounds) that your application will use. /extensions Contains the various Extensions that your application might use. /hooks Contains any hooks that your application uses. /modules This is where your controllers live. This directory is divided into: /admin Contains your admin controller modules. /<module_name> /<module_name_2> etc. /front Containers your front-end (public) controller modules /<module_name> /<module_name_2> etc. /setup Installation and upgrade scripts that your application will use when required. /sources The directory containing your models. /<model_type> /<model_type_2> etc. /tasks Contains scripts that are executed periodically by IPS4's task system. /widgets Contains scripts that will output widgets, to be used in IPS4's block manager system. \IPS\Application::getRootPath(); If you need to reference the path to your application files then the \IPS\Application::getRootPath( 'appkey' ) method should be used. This is to make sure the correct path is used regardless of the server environment.
-
EditorLocations extension In order to display the editor field that enables users to leave comments, you will first need to create the EditorLocations extension for your application. For more information on doing this, consult the WYSIWYG Editor guide. Displaying comments It's up to you how comments are displayed in your application. Some applications will display comments in a traditional way, while others may require something much more custom. However you choose to display them, you need to include some standard attributes in your markup in order for functionality like live updating and pagination to work correctly. Here's a very basic approach: <div data-controller='core.front.core.commentFeed' data-feedID='messages-{$item->id}'> {{if $item->commentPageCount() > 1}} {$item->pagination()|raw} <br><br><br> {{endif}} <div data-role='commentFeed'> {{if count( $item->comments() )}} {{foreach $item->comments() as $comment}} {$comment->html()|raw} {{endforeach}} {{else}} <p data-role='noComments'>{lang="no_comments"}</p> {{endif}} </div> <div data-role='replyArea'> {$item->commentForm()|raw} </div> </div> Generic comment templates will be used to build the actual body of each comment. You can customize these via properties in your model; see the model guide for details.
-
In order to use comments, you'll need to make a few adjustments to your content item model too. Class property changes You will need to add new properties to your content item model. public static $commentClass = 'string'; This should be the full path to your comment model class. For example: public static $commentClass = 'IPS\yourApp\YourCommentClass'; protected static $firstCommentRequired = boolean; If your content item requires a first comment (e.g. the Forums app requires the first comment, which appears as the first post in a topic), you can set this property to TRUE. By default, it is FALSE. You also need to add new values to your content item model's $databaseColumnMap, as follows: num_comments Required. Value should be the column name that holds the total comment count for the content item. last_comment Optional. Value should be the column name that holds a timestamp of when the last comment was made. last_comment_by Optional. Value should be the column name that holds the ID of the member who made the last comment. last_comment_by Optional. Value should be the column name that holds the username of the member who made the last comment. Although optional, the last three properties above can make your application more efficient if they are specified and used. Additional content item model methods available integer static getCommentsPerPage() Returns the number of comments that should be shown per page. The default is 25. You can override this in your model to change the number shown per page, for example to base it on a setting within your application. integer commentPageCount( [ boolean $recache ] ) Returns the number of comment pages the item has. $recache (boolean, optional, default FALSE) Forces a recalculation and recache of the result of this method. string commentPagination( [ array $queryString [, string $template [, integer $pageCount [, \IPS\Http\Url $baseUrl ] ] ] ] ) Returns the HTML for the pagination of the content item comments. $queryString (array, optional) An array of additional query string parameters to be added to pagination URLs (for example, current sorting options). $template (string, optional, default 'pagination') The name of the template to use to generate the pagination. Either 'pagination' or 'miniPagination'. $pageCount (integer, optional) The number of pages of comments on this item, if known. If NULL, will be calculated on demand. $baseUrl (\IPS\Url\Http, optional) Allows you to specify an alternative base URL to use for the pagination links. By default, the item's normal base URL will be used. mixed comments( [ integer $limit [, integer $offset [, string $order [, string $orderDirection [, \IPS\Member $member [, boolean $includeHidden [, \IPS\DateTime $cutoff [, mixed $extraWhere [, boolean $bypassCache ] ] ] ] ] ] ] ] ] ) Returns the comments on the content item. If $limit is 1, will return an \IPS\Content\Comment object. For all other params, will return an array of comments if any exist, or NULL. $limit (integer, optional) The number of comments to fetch. By default, the number returned by static::getCommentsPerPage is used. $offset (integer, optional) The offset from which to return comments. By default, whatever value exists in \IPS\Request::i()->page is used. $order (string, optional, default 'date') The field on which comments should be sorted. $orderDirection (string, optional, default 'asc') The direction in which comments should be sorted, either 'asc' or 'desc'. $member (\IPS\Member, optional) If a member object is provided, will fetch comments only by that member. $includeHidden (boolean, optional) Determines whether hidden comments should also be returned. By default, the currently-logged in member's permissions will be used to determine this value. $cutoff (\IPS\DateTime, optional) If provided, only comments posted after this time will be returned. $extraWhere (string or array, optional) Extra parameters to pass into the WHERE clause of the underlying query. $bypassCache (boolean, optional, default FALSE) Determines whether comments should be forcefully reloaded rather than fetched from the cache. string commentForm() Returns the HTML for the comment form \IPS\Http\Url lastCommentPageUrl() Returns the URL for the last page of comments, as an \IPS\Http\Url object. boolean canComment( [ \IPS\Member $member ] ) Indicates whether the member is able to comment on the item. $member (\IPS\Member, optional) If provided, will use this member's permissions when checking. By default, the currently-logged in member will be used. Other behavioral changes The stats() method will now return an additional key containing the number of comments on the item.