Jump to content

SeNioR-

Members
  • Posts

    1,148
  • Joined

  • Days Won

    5

Reputation Activity

  1. Like
    SeNioR- reacted to Esther E. for an entry, IC5: Developer Center   
    As part of our commitment to encourage 3rd party development and extension, we have given our Developer Center a much needed makeover. A picture is worth a thousand words, but how about a video?
     
    Highlights
    The Developer Center now has its own dedicated tab in the ACP. What were previously tabs are now displayed on individual screens, making for a far less cluttered UI. You can easily switch from one application to another using the main menu or the button at the top right of the screen. We've implemented UI for some JSON files that previously had to be manually created; specifically acpsearch.json and furl.json We've replaced the "Support" button at the top of the ACP with a more helpful "Quick Links" dropdown menu. While this is not specific to developers, with easy access to things like the Task Manager and clearing caches, it's very handy for troubleshooting!  
    Application Landing Page
    When you open the Developer Center for a particular application, the landing page is designed to help you quickly access common functions, and to help you find any potential issues within your code.

     
    The Application Scanner currently checks for:
    Missing Admin CP Language Strings Missing Front-End Language Strings Missing EditorLocations extensions Missing FileStorage extensions Missing FrontNavigation extensions Missing FURLs Missing Email Templates  
    Language strings are grouped so that can you easily see where the missing strings were detected.

     
    We will continue to expand the scanners over the course of the next few months.
     
    Thoughts?
    What do you think? Are there any other useful features you'd like to see added to the Dev Center? What kind of scans can we implement on the landing page?
  2. Like
    SeNioR- reacted to Esther E. for an entry, IC5: Commerce   
    One of the areas we have reviewed in Commerce is the way that we handle custom items. Previously, many of our features were limited to Commerce Products. Even items such as Subscriptions and Download Files were not fully integrated. In Invision Community 5, we have looked at ways to improve the overall experience.
     
    Icons and Images
    A small, but important change: displaying the item icon when an image is not available. In previous versions, if no image was available, the checkout and client area displayed a standard "box" icon for all items. In IC5, we now show the icon defined in your Item extension.

     
    Product Details
    Line item details are displayed on the checkout screens, as well as on the Invoice. However, this functionality was restricted to custom package fields, which are only available for Commerce Products. This logic has been moved to a new extension method, detailsForDisplay.

     
    Coupons
    A very popular request is to create coupons for specific items that are not Commerce Products. Previously, coupons could either be applied to the entire purchase or to specific packages. We have added the following methods to the Item extensions to allow you to integrate your items with the coupon form.
    couponFormElements
    Returns an array of elements that will be shown on the coupon form. If no elements are returned, your item will not be listed. saveCouponForm
    Process the values of the fields defined in your couponFormElements method. This method returns an array of data that will be stored with the coupon. isCouponValid
    Check if the coupon is valid for this item. New default coupon form:

     
     
    Autopay
    When Commerce generates renewal invoices, we attempt to take a payment if a user has a card on file. We have moved this functionality to \IPS\nexus\Gateway::autopay(). Your gateway must also have the SUPPORTS_AUTOPAY constant set to true in order for this to work.
    With the new logic, when a renewal invoice is generated, the task will loop through all available methods. If autopay is supported, it will attempt to take payment using that payment method.

     
    We've tried to include the most popular requests that we've seen for custom items and payments. What do you think? Have we missed anything? What are some of the requests you've received for custom item integration?
  3. Like
    SeNioR- reacted to Esther E. for an entry, IC5: Updating your Applications   
    As we get closer to our first release, we'll be discussing how to update your custom applications to be compatible with IPS v5. We know this can seem like a daunting task, especially since not all changes will be immediately obvious, so we'll be walking through this step by step.
     
    Updating Source Classes
    Classnames should no longer start with an underscore. All our source classes are now strictly typed, so any of your classes that extend pretty much anything (Content Items, Nodes, Active Record) will need to be updated with the correct method signatures and property types. Almost all Content interfaces have been converted to traits (e.g. \IPS\Content\Pinnable, \IPS\Content\Lockable). Your content classes should have use statements instead of implements, and if you are overloading any trait methods, verify that it is properly declared.
    The following interfaces have not been moved to traits:
    \IPS\Content\Embeddable
    \IPS\Content\Filter
    \IPS\Node\Permissions \IPS\Content\Searchable has been removed entirely and replaced with a SearchContent extension. Recommended: We no longer use FQN in our code. This is not required for v5 compatibility, but a recommendation for best practice.

    A few examples of the changes to the code base, showing strictly typed function signatures and using traits versus interfaces
    Updating Extensions
    All extensions now have an abstract class that should be extended. Most of these can be found under \IPS\Extensions. The abstract class is typically the same name as the extension type (e.g. EditorLocations extend EditorLocationsAbstract). Verify that your extensions use the correct abstract class and that all your method signatures and properties are declared correctly. Remove deprecated extensions. See this blog entry for a complete list. Convert your CreateMenu extensions to a UserMenu extension. Convert your MemberSync extensions to a Listener.  
    Replacing Code Hooks
    The following is a general list of the most common types of code hooks. Obviously, we cannot predict, nor support, all possibilities, but we have tried to cover the basics here.
    Hooks on content classes should be replaced with Listeners or UI Extensions. Hooks on the Dispatcher (e.g. for loading JS/CSS) should be converted to Loader Extensions. Hooks on commerce items should be replaced with Listeners. Hooks that add functionality (e.g. Commerce gateways, Login handlers) should be moved to the appropriate extensions.  
    Replacing Theme Hooks
    As with code hooks, below is a list of common uses for theme hooks.
    Theme hooks that add to the user dropdown menu should be moved to a UserMenu extension. Theme hooks that add classes or attributes should be moved to UI Extensions. Theme hooks that insert HTML should be moved to template hooks.  
    Please let us know in the comments if there is anything that we may have missed, or if something is unclear. We would like to make this transition as smooth as possible.
  4. Like
    SeNioR- reacted to Matt for an entry, IC5: Theme Tools   
    Theming has been a core component of Invision Community since its inception, and this continues with Invision Community 5, but in a very different way.
    If you haven't already seen Ehren's blog on the new Theme Editor, please do take the time to watch it. The all-new theme editor reduces the complexity of theming by taking complex concepts like HSL CSS variables into a pretty slick UI that almost any Invision Community owner can use to personalise or brand match to any existing properties.
    Ehren will talk more on the technology behind the theme editor in another developer blog soon, but the short version is that the CSS framework has been completely rewritten from scratch with a new approach to how CSS classes interact with page elements.
    Of course, if you're reading this, you'll want to know what tools you have for more advanced theming in v5.
    Custom templates and template hooks
    Invision Community 5 merges the concepts of custom templates and template hooks into a single feature. In the past, you could edit templates directly and create theme hooks. With Invision Community 5, these features are replaced with the new custom template system.

    You can create new templates, which you can use in other custom templates via the short tag: {customtemplate='key'}. 
    You can also hook into specific areas with a custom template allowing you to insert code before the opening tag, after the opening tag, before the closing tag or after the closing tag.
     
    CleanShot 2023-10-19 at 13.17.16.mp4
    For example, if you wanted to add something custom before the reply editor when viewing a topic, you would target that area like so:

    The result, when viewed on the front end, is as follows:

    These hookable areas are defined by a special tag that we add to the core templates. We would expect a lot of requests through the beta release and will likely create a request form so we can process them. We will try and accommodate as many areas as possible.
    While direct template editing is no longer possible in Invision Community v5, the new custom template and hook system allows you to add new functionality, while the new CSS framework makes it easier to target and change elements without the need to edit templates.
    We also added a suite of new development tools to enable you to target menus, data attributes and other areas where developers commonly had to edit templates before.
    The good news is that now custom templates are not built on top of our 'master' template engine; they are virtually upgrade-proof and do not require manual merging.
    Theme Designer Mode
    Those who create themes for others have some extra tooling to enable them to build truly custom themes.
    Even though the theme editor has space for custom CSS, there is always a need for CSS that your customers cannot edit, and Invision Community 5 has a special area for that once Theme Designer Mode has been enabled.

    You also can add any ad-hoc javascript for when you want to hide elements or provide custom interactions.
    As direct CSS editing and direct template editing are no longer possible with Invision Community 5, there is no need for a 'sync' tool to copy from the filesystem.
    Conclusion
    The new front-end theme editor is now the primary way to manage themes. This is where you upload logos and toggle settings.
    As you can see, theming may look different in Invision Community v5. Still, the new custom templates, theme designer tools and UI extensions provide a lot of functionality that means you can do nearly everything you did in v4, but often in an easier way.
    I'm sure you'll have many questions, so please add them below, and we'll do our best to answer them for you.

  5. Like
    SeNioR- reacted to Esther E. for an entry, IC5: UI Extensions, Part I   
    Only a little over a week into our development tools announcements, and there is already lots of buzz about our new UI Extensions. The UI Extensions handle a variety of functionality, and we will discuss them all in detail, over the course of multiple blog entries. For today, we'll start with an introduction and an overview of some of the basic usage.
     
    Features and Functionality
    UI Extensions are extensions to a single content class - Nodes, Items, Comments, or Reviews. With a UI Extension, you can:
    Add custom CSS classes and data attributes Add options to content menus Add badges to content item headers Add fields to content forms ACP-related functionality (for nodes) And a couple of other small things that we'll cover here.

    Setup
    The Application Developer Center has 4 new options in the Extensions tab:
    UIComment UIItem UINode UIReview To add a UI extension, simply create a class under the appropriate extension type.
    Note: We are working on improving this process, however, those changes will likely be introduced at a later date.
    The default extension file will be generated in the appropriate directory within your application's extensions folder. All UI Extensions are abstracted, so if you omit a method from your class, or if new methods are introduced later on, your extension will not throw an error.
    All UI Extension methods receive the object as the first parameter.
     
    UI Extensions for... UI
    The idea for UI Extensions was born when we were reviewing the most common third-party development hooks. With the removal of theme hooks, we needed a way for developers to add custom CSS and attributes to areas such as topic rows, the author panel, among others. Even with the theme hooks in v4, the way to accomplish this was less than ideal. Adding a CSS class typically required at least 2 hooks per template - one to determine the correct class (usually based on custom logic) and one to insert the class as a variable. It was tedious and finicky at best.
    All UI Extensions include the following methods:
    css
    Returns an array of CSS classes that will be applied to the object dataAttributes
    Returns an array of data attributes (as "key=value", "key=value") that will be applied to the object To insert those values into the appropriate location, our templates now contain the following syntax:
    {$object->ui( 'css' )} and
    {$object->ui( 'dataAttributes' )} Let's examine the Content::ui() method (identical to Model::ui().)
    public function ui( string $method, ?array $payload=array(), bool $returnAsArray=false, string $separator = " " ) : array|string The ui method accepts 4 arguments: the method name, an optional payload (determined based on the method being called), the option to return as an array (vs a string), and an optional separator (when data is returned as a string). The defaults for this method were set for the simplest, shortest syntax within the templates, as seen above. You may also see syntax like this:
    foreach( $this->ui( 'menuItems', array(), TRUE ) as $key => $link ) { $links[$key] = $link; } As you can see, in this case the ui method will return the results as an array.
     
    Class-Specific Methods
    Some of our extensions include methods that are applicable only to objects of that type.
    UIItem::sidebar()
    Returns HTML that will be included in the contextual sidebar when viewing the item UIComment::authorPanel()
    Returns HTML to be inserted into the author panel of a post Note: All methods in the UIComment extension are also available in UIReview.
     
    We hope this entry gave you a glimpse into what will be available with this new tool, and a better understanding of the direction we are taking with our toolkit. We will discuss the other features of this tool in upcoming blog entries.
  6. Like
    SeNioR- reacted to Esther E. for an entry, IC5: Extensions   
    We've been dropping hints about various development features that haven't yet made their appearance in our previous blog entries. Now that hooks are no longer a possibility, we've expanded our Extensions system to allow developers to integrate with other areas within the framework.
    This blog entry will give an overview of our new Extensions. We are working on updating our developer documentation to include these changes.
     
    AccountSettings
    Allows you to add tabs to the Account Settings page. This extension contains two methods:
    getTab
    Returns the key for the tab (or null to hide) getContent
    The tab content  
    Loader
    This extension was created primarily to allow you to load Javascript and CSS files in areas outside of your application, but has since been expanded to include other functionality. It is essentially an extension on the Dispatcher.
    Available methods:
    css
    Returns an array of CSS files to load js
    Returns an array of JS files to load checkForRedirect
    Redirect users to another location. This is especially useful for custom applications that would have previously bypassed an existing controller. customError
    Show a custom error message to the user instead of the standard IPS error messages.  
    SearchContent
    This is used to allow your application's content to the Search Index. Previously, the framework relied on the ContentRouter extension for this, and the use of the \IPS\Content\Searchable interface. The interface has been removed, and searchable classes are determined by the new extension.
    The SearchContent extension contains one required method, supportedClasses. You can also use this extension to override our default search logic for your content.
     
    Other New Extensions
    LoginHandler
    Allows you to create additional Login methods UIComment/UIItem/UINode/UIReview
    UI Extensions, described here, here, and here UserMenu
    Allows you to add content to various menus. Additional information can be found here.  
    New Commerce Extensions
    The following new extensions have been added to Commerce:
    Gateway
    Allows you to create new payment gateways LicenseKey
    Allows you to add new methods for generating and managing license keys Payout
    Allows you to create gateways for payouts  
    Deprecated Extensions
    The following Extensions are no longer supported and have been removed:
    BBCode ContentModeratorPermissions (use ModeratorPermissions instead) CreateMenu (replaced by UserMenu) IncomingEmail MemberForm  
    Reminder: Send us your Feedback
    Send us your questions or use-cases by submitting a topic here. Please note that this is a private forum; you will not see topics posted by others, so you are free to share code samples if necessary. We will review your questions, and then aggregate them into an FAQ. The deadline for your question to be considered for the FAQ is October 15. After that you may still submit questions in the Contributor forum, where we will do our best to respond.
     
  7. Like
    SeNioR- reacted to Esther E. for an entry, IC5: UI Extensions, Part III   
    By now you might be getting a little tired of hearing about our UI Extensions, but we still have a few more features to talk about. We showed you how to add CSS and data attributes to content. We discussed how to add form fields and menu items. In this final entry on this tool, we'll talk about working with Nodes.
     
    ACP Tools
    Nodes are different than the Items and Comments, as they are typically managed in the ACP and not on the front-end. Therefore, we needed additional extension methods to allow developers to handle custom actions.
    Let's take a look at Nodes in the ACP.

    There are a few areas where developers may need to insert custom logic. The UINode extension includes the following methods:
    rowButtons
    Returns an array of action buttons that will be added to the control strip on the right. This method functions identically to the Model::getButtons() method. rowHtml
    Inserts custom HTML to the left of the control strip. rowBadge
    If a badge should be displayed, return an array with the CSS class and language string. Note that anything defined in the base class get__badge() method will take precedence over your extension.  
      No Entry
    It is important to note that not all Node classes support the form-related methods. We have of course added support for all content containers, such as Forums and Calendars. We will consider including support for other classes upon request, however, nodes that handle infrastructure (e.g. Theme, Lang) will not be supported.
    We have also locked down some system-level classes (not all) where any extension is potentially destructive. Classes such as Application and Module cannot be extended.
     
    OK, so what CAN I still do? AMA (well, almost anything).
    We still have a few more tools to show you, but at this point we'd like to hear from you. We know there is still a lot of uncertainty around how to migrate your modifications from v4 to v5, and we're here to assist with that. Send us your questions or use-cases by submitting a topic here. Please note that this is a private forum; you will not see topics posted by others, so you are free to share code samples if necessary. We will review your questions, and then aggregate them into an FAQ. The deadline for your question to be considered for the FAQ is September 1. After that you may still submit questions in the Contributor forum, where we will do our best to respond.
     
     
  8. Like
    SeNioR- reacted to Esther E. for an entry, IC5: Menus   
    Action and Moderation Menus can be one of the most tedious development tasks, while also being critical to user experience.
    For example, we may add support for pinning/unpinning content, then we need to remember to include the ability to pin/unpin that content in all the HTML templates. 3rd party developers add screens inside their applications, and then they need to add a link to the User Menu to make that accessible.
    With Invision Community 4, this would require a template hook targeting fairly complex classes and children that was susceptible to structural changes to templates between versions.
    In Invision Community 5, we have made significant changes to menu creation in order to streamline the process, and also to allow 3rd party developers better accessibility.
     
    New Helper Classes
    Menus are now built using helper classes, rather than relying on lengthy HTML templates. A menu is created by initializing a new Menu object.
    $menu = new Menu( 'AccountMenu' ); We can then add elements to the menu.
    $menu->addTitleField( 'menu_content' ); $menu->add( new Link( $member->url(), 'menu_profile', icon:'fa-solid fa-user' ) ); $menu->addSeparator(); $menu->add( new Link( Url::internal( "app=core&module=system&controller=markread", "front", "mark_site_as_read" )->csrf()->addRef( Request::i()->url() ), 'mark_site_read', dataAttributes: [ 'data-action' => 'markSiteRead', 'data-controller' => 'core.front.core.markRead' ], icon: 'fa-solid fa-eye' ) ); The most common menu element is the Link. This will generate the appropriate <li> element within the menu. You can define the URL, CSS class (default is ipsMenu_item), data attributes, icon, title, among other properties.
    Titles and Separators are added using the Menu::addTitleField() and Menu::addSeparator() methods respectively.
    You can also insert custom HTML into the menu using the Menu::addHtml() method.
    In your HTML template, you would then simply display the menu object as a string.
    {{if $menu->hasContent()}} {$menu|raw} {{endif}} The menu templates will include the link that opens the menu, as well as the menu itself.
    You'll notice that the above contains a call to the hasContent() method. This method will check if the menu object has any elements inside; if a user does not have permission to any of the elements, nothing will be displayed.
     
    Content Menus
    Almost all content items and comments (and reviews) require some kind of menu for moderation. Previously, this meant creating large chunks of redundant HTML code throughout the codebase. We've implemented \IPS\Content\Item::menu() and \IPS\Content\Comment::menu() to build these menus in a central location. The new methods include checks for whether a feature is in use and whether the user has permission to perform this action.
    Example:
    if( IPS::classUsesTrait( $this, 'IPS\Content\Pinnable' ) AND $this->canPin( $member ) ) { $links['pin'] = new ContentMenuLink( $this->url()->csrf()->setQueryString( array( 'do' => 'moderate', 'action' => 'pin' ) ), 'pin' ); } Now, the HTML template simply contains:
    {$entry->menu()|raw} (Note: Yes, these content menus can be extended using... you guessed it. UI Extensions.)
     
    Other Menus
    We have also migrated the following menus to the new structure:
    User Menu Mobile Menu Create Menu  
    Badges
    Another area with redundant HTML was our content badges. For example, pinned topics will display an icon on both the topic list and the topic header. We have created helper classes for badges and badge icons to centralize this logic. Within the new Item::badges() method, we build an array of icons that will be shown.
    if( IPS::classUsesTrait( $this, Featurable::class ) AND $this->isFeatured() ) { $return['featured'] = new Icon( Badge::BADGE_POSITIVE, 'fa-solid fa-star', Member::loggedIn()->language()->addToStack( 'featured' ) ); } The above generates a badge icon with the badge type ipsBadge--positive (constants have been declared for all common types, but any class can be used), the star icon, and the "featured" language string as the tooltip.
    In our template HTML, we now have
    <div class='ipsBadges'> {{foreach $entry->badges() as $badge}}{$badge|raw}{{endforeach}} </div>  
    UserMenu Extension
    Now that we've moved the menus into the codebase and out of the templates, we needed a way to allow 3rd party developers to insert their own menu items. We've introduced a new extension called UserMenu.
    The UserMenu extension contains the following methods:
    accountMenu
    This method allows you to add menu elements to the user menu. The method includes a parameter to allow you to add elements in one of 3 places within the menu: content, settings, or logout. mobileMenu
    Allows you to add elements to the mobile navigation menu. All elements are inserted before the "sign out" option. createMenu
    Replaces the CreateMenu extension, which has been deprecated. accountSettingsLinks
    Allows you to add links to the inner sidebar in the Account Settings overview tab (under the link for Notification Settings). Note: No, this does not add tabs to the Account Settings page, but fear not, that's coming. (Not in the UI Extension.)
    userNav
    This method will insert HTML in the user bar, to the left of the Create Menu. mobileNav
    Similar to the userNav method, but inserts HTML into the mobile navigation header.  
    What do you think of our changes to the Menus? Let us know in the comments below.
  9. Like
    SeNioR- reacted to Esther E. for an entry, IC5: Introduction to Listeners   
    I'm very excited to be posting my first blog entry for IPS, and thrilled that this is what I get to post.
    When we started planning the new development tools for v5, we looked at existing resources - from the marketplace, from some contributors, and from our own managed clients - and asked, what is it that developers find themselves doing the most often? Matt’s previous blog entry gave a brief summary of some of those functions. Today’s blog entry is going to focus on one of our powerful new tools, Listeners.
    One common reason for a code hook was to execute custom code when a specific action occurs. For example, when a topic is created, or when a new reply is posted. Listeners allow you to execute your code at key points in the workflow, without the worry of finding exactly the right hook location.
    Here is an excerpt from the BlogComment listener in our Cloud application:

     
    Creating Listeners
    Let’s start with the application’s Developer Center.

    We’ve added a new tab for Listeners. This tab lists all your existing listeners, as well as the class on which it is listening.
    You’ll notice that each listener can only observe a single class. While this may seem slightly tedious, the idea here was that as a developer, you should be conscious of what class you are working with. It also eliminates the need to check what type of object is being passed preventing accidents and unintended consequences when missing class checks.
    When you add a listener, there are several listener types available. We will discuss each one in detail.

     
    Content Listener
    This listener is fired on an Item or Comment (or Review) class. When adding a Content Listener, you must specify the class you are observing. When you hit Save, there is a validation check in place to ensure that the class exists, and that it is a valid class for the selected listener type.
    Content Listeners have the following methods available. All methods are included in the default listener file that is generated.
    onLoad
    Triggered when an object is loaded (in Content::constructFromData) NOTE: Be careful! This event could be fired at unexpected times. If you’re executing code here, you may want to check the dispatcher instance to verify that your code is running where you expect.
    onBeforeCreateOrEdit
    Fired when a form is submitted, before it is saved. This is the equivalent of Item::processBeforeCreate and Item::processBeforeEdit. This method includes a parameter to indicate whether this is a create or edit. onCreateOrEdit
    Fired after a form is saved. This is the equivalent of Item::processAfterCreate and Item::processAfterEdit. This method includes a parameter to indicate whether this is a create or edit. onDelete
    Fired after an object is deleted. onStatusChange
    Fired when any moderation action occurs. For example, when an item is pinned/unpinned, locked/unlocked. The moderation action is passed as a parameter so that your code can take that into account. onMerge
    Triggered AFTER an item is merged. onItemView
    Triggered when an item is viewed and the view count is incremented.  
    Invoice Listener
    An Invoice listener is fired only on the \IPS\nexus\Invoice class. This listener does not require you to specify a class to extend.
    The Invoice listener includes a single method, onStatusChange. This is fired when the invoice is saved and the status changes (pending/paid/expired/canceled).
     
    Member Listener
    The Member listener will be familiar to many of you. We have taken the MemberSync extension and moved it in its entirety to a listener, as it was a better fit for this structure. All the previous methods that were available are still available here. We have also added the following new methods:
    onJoinClub
    Fired when a member joins a club. If approval is required, this is fired after they are approved. onLeaveClub
    Fired when a member leaves or is removed from a club. onEventRsvp
    Fired when a member responds to an event. The response is included as a parameter to this method.  
    Commerce Package Listener
    The Commerce Package listener is fired on any implementation of \IPS\nexus\Invoice\Item. You must specify the class that you are observing.
    The methods are the same as those that are available in an item extension.
    onCancel onChange onDelete onExpireWarning onExpire onInvoiceCancel onPaid onPurchaseGenerated onReactivate onRenew onTransfer onUnpaid  
    Some Technical Notes
    All listener files will be generated in a “listeners” directory within your application. Your application’s data directory will include a listeners.json file that defines all your listeners. The json file is automatically generated when you add/remove a listener. All listener methods are optional. The default class that is generated will include all available methods, but they do not have to be present in your file. All listener methods are return type void. If a listener method fails, an exception will be thrown when IN_DEV is enabled. In production, the exception will be logged with a reference to the listener class and the event on which the exception occurred.  
    Firing Events
    Your code can fire any existing event using the Event::fire method.
    Example:
    Event::fire( 'onBeforeCreateOrEdit', $comment, array( $values ) ); The Event::fire method is called statically and accepts an event name, the object on which the event will be fired, and an array of additional parameters (varies according to the event that you are triggering).
    This concludes our introduction to Listeners. We do intend to implement additional listener types and events based on your feedback and as the need arises.
  10. Like
    SeNioR- reacted to Matt for an entry, Introducing Invision Community 5's development tools   
    When planning Invision Community 5, we knew we had a unique opportunity to hit the reset button.
    It's hard to believe, but how we work with the framework has been the same since 2013. The priorities we held a decade ago no longer align with our current vision.
    The landscape of modern frameworks has evolved, and we have adapted accordingly.
    When we initially designed the Invision Community 4 framework all those years ago, our goal was to create an open development platform. We aimed to empower you with the ability to extend virtually every function we built, granting complete freedom to shape our UI, workflows, and functionality according to your needs.
    However, over the decade, we have realised that this freedom has inadvertently become a prison. While monkey patching allowed the overloading of any method we had written, it came at a significant cost. Even the slightest change to our original method signatures could break an entire community, forcing you to update your applications.
    Ironically, the more we strived to enhance our framework, the less stable your applications became.
    We dismissed requests for proper workflows like extensions, webhooks, and event listeners, urging you to rely solely on method overloading, often having to copy chunks of code just to add a few lines of your own.
    Invision Community 5 represents a much-needed reset. It is a moment to reassess everything we know about extending frameworks and construct definitive pathways and workflows that serve you better.
    Our aim is for you to continue crafting exceptional applications that bring fresh functionality to the Invision Community while protecting the integrity of our core functionality.
    Change can be intimidating, but let us embrace this opportunity to bid farewell to outdated and fragile tools and pave the way for a collaborative future with precision-designed resources instead.
    In the coming weeks, we will delve deeply into the new development tools offered by Invision Community 5, but today, I wanted to give you a brief overview of what's to come for code development. We will do a near-future entry on creating themes with Invision Community 5.
    Out with the old
    Monkey patching via code hooks was the primary way to add functionality to Invision Community. However, it meant that we could not update our code base without risking breaking many popular applications, a situation that will only get worse as PHP starts to lock down type hinting and casting.
    Furthermore, IDEs have a tough time working out relationships between classes requiring special tools to create alias files to allow full use of many advanced tools of PHPStorm and other editors. Finally, monkey patching relied on heavy use of eval() which is not a very efficient PHP method.
    Monkey patching has been removed in Invision Community 5.
    Your IDE with Invision Community 4.

    Your IDE with Invision Community 5.

     
    Template hooks, as you know them, have also been removed. I only mention this now as they often go hand-in-hand with code hooks to add items to menus, data-attributes to blocks and CSS classes to many areas. We will do a more thorough blog on theme editing soon, but we still retain a way to hook into key areas.
    In with the new
    We will write a series of developer blogs to look in more detail at the new systems, but here is a quick overview of the new tools and a brief description of what they are capable of.
    Content Menus
    We have removed much of the menu logic for content items and comments from templates and created a simple, extensible way to add links to commonly used menus, such as the item moderation menu and the per-post 'three dots' menu. You no longer need a template hook to perform such a basic task.

    UIExtension
    This framework provides you with an easy way to add CSS, data-attributes and even templated HTML into specific areas within nodes and content items/comments. A common reason to create template hooks was to tweak the CSS classes or add data-attributes for client-side scripting.

    In the same way that we've stripped menus out of templates, we've removed the content item badges (pinned, hidden, etc.) and into the UIExtension making it easy to add your own badges to this area without the need for template or code hooks.
    Finally, UIExtension can add form fields into Invision Community content forms.
    Event Listeners
    The easiest way to describe this is like MemberSync but for content (items and comments), members, Commerce invoices and Commerce packages.
    Do you need to run your code each time a forum post is made? Not a problem. Do you need to run your code when a topic is locked? Perhaps when an item is viewed? All this and more is possible via the new listeners.
    The advantage is that you don't need to copy chunks of our code when overloading a single method in a hook. You write your clean code in an object-specific listener.

    What else?
    We have also undertaken a long overdue code clean-up. Every single file has been updated to update return types and function signature types and to use aliases instead of fully qualified names (for example, new Url() instead of new \IPS\Http\Url()).
    Many methods have been removed from the Content classes and moved into traits. Likewise, many interfaces are now traits to reuse code properly, reducing the behemoth-sized classes.
    Elsewhere, all the search indexing logic that was entwined in content and node classes has now been moved to the extension system, further reducing the noise and volume of key classes.
    A Quick Recap
    Generic broad reaching tools such as monkey patching and template overloading have been removed. New precision tools with a specific use-case have been created. There are less opportunities to overwrite and change our UI and functionality but easier ways to extend and create new functionality. The future
    We have worked hard on these development tools to ensure that most of what you do now can be achieved in Invision Community 5. We have had input from various stakeholders, including those who regularly create modifications for Invision Community to ensure our new tools are fit for purpose.
    Through the alpha and beta testing phase, we want your feedback, and we will listen to your suggestions. We cannot promise that you can do everything with Invision Community 5 that you currently do, which is intentional, but we are confident that you can still hit all the major beats. We want to protect our UI and functionality a little more but encourage you to build amazing new functionality to work alongside Invision Community 5.
    Together, we will shape the next era of Invision Community.
  11. Like
    SeNioR- reacted to Matt for an entry, Development update for October 2022   
    Welcome to our October developer's update!
    After a frantic few months of working on the PHP8 transition, we made it across the line with our November release (4.7.4), which requires PHP8 as the minimum version.
    Reminder: Invision Community 4.7.4 will disable plugins and applications that are not compatible with PHP8, and the only way to re-enable them is to upload a new version. Hopefully, you've had time to get your apps updated and through our review system. Thank you again for your patience throughout this process. The next big change will be PHP8.2, which changes how DateTime is overloaded, but that's a headache for 2023.
    Make sure you use PHP8 with your local development environments and set your IDE to PHP8 if it has this feature.

    If you need a refresher on the new functionality that comes with PHP8, then I recommend this blog or this video.
    Impacting Code Changes
    We've been very careful to avoid adjusting any parameter signatures this month, and we will endeavour to get you plenty of notice if we need to change things on a central method.
    The main change to look out for this month is the change to IPS\<app>\extensions\core\ContentRouter
    /** * @brief    Can be shown in similar content */ public $similarContent = TRUE; We added a public method variable to note if this content type can be used in the similar content widget. This change fixes a bug where some content types, like Commerce packages, appeared in the widget but with incompatible metadata.
    Holiday Release Schedule
    It's that time of year when we start planning releases around the Thanksgiving and Christmas holidays. We try and avoid larger releases at this point in the year to reduce the stress levels on our support and development teams. No one wants a crisis during what should be a relaxing time with family and friends.
    The current schedule looks like this:
    2 November: November release (4.7.4) First week of December: Smaller bug-fixing release (4.7.5) Early January: Patches or a very focused bug-fixing release (4.7.5.1/4.7.6) February: Full monthly releases as usual. Deprecations
    This month, we removed the older guest page caching. Those looking for a better replacement are having success with a free plan from Cloudflare.
    We also removed the Facebook promotion tool as Facebook keeps raising the bar for approval, and we want to focus on a Zapier replacement coming soon. Finally, we also removed Vigilink, which no longer works.
    Other News
    The November release features commits from @HeadStand, who is working with us part-time to chew through the backlog and work on feature improvements. She is a coding machine and has filled my inbox with GitHub pull request notifications which I'm very happy to receive!
    That's all for this month, happy developing!
  12. Thanks
    SeNioR- reacted to Matt for an entry, Development update for September 2022   
    Welcome to our September developer's update!
    I can say with some confidence that both the Invision Community team and our marketplace developers have had a busy September as we prepare for PHP8. Thank you for your patience with this necessary step. As I've mentioned elsewhere, PHP8 is a pretty big jump and is much more strict about many things, and now throws fatal errors when before it would have been a harmless notice.
    PHP7 is now end of life, and security updates will no longer be available from November.

    Preparing for PHP8
    I've talked about this on the forums a lot over the last few weeks, but I'll summarise the timeline here so you can prepare your plugins and apps to be PHP8-ready.
    September release (4.7.2): The PHP8 scanner will disable any plugins and applications that would cause issues with PHP8, but Invision Community owners can re-enable them if they choose to do so.
    October release (4.7.3): A warning shows in the AdminCP if Invision Community is installed with PHP7. As of October, the PHP8 scanner will disable plugins, but they can be re-enabled.
    November release (4.7.4): The PHP8 scanner will disable plugins and applications found not to be PHP8-ready. They cannot be re-enabled via the AdminCP. The only way to re-enable them is to upload a new version.
    Code changes to be aware of
    October hasn't been the biggest of releases, but it does come with the new Events front-end for Calendar, and this changed the parameter signature for getItemsWithPermission(), which is probably the most overloaded method we have.
    The new parameter signature is as follows:
    public static function getItemsWithPermission( $where=array(), $order=NULL, $limit=10, $permissionKey='read', $includeHiddenItems=\IPS\Content\Hideable::FILTER_AUTOMATIC, $queryFlags=0, \IPS\Member $member=NULL, $joinContainer=FALSE, $joinComments=FALSE, $joinReviews=FALSE, $countOnly=FALSE, $joins=NULL, $skipPermission=FALSE, $joinTags=TRUE, $joinAuthor=TRUE, $joinLastCommenter=TRUE, $showMovedLinks=FALSE, $location=NULL ) Note, $location has now been added to the list. If you overload getItemsWithPermission then you will need to update any hooks with his new parameter, or it will be flagged via the PHP8 scanner. The reason for this addition is to allow an easier way to get items via a latitude and longitude lookup. If you manage this elsewhere, you might find using getItemsWithPermission a much simpler way.
    @Daniel F has also been working on improving the GraphQL API, and the GraphQL library has been updated to 14.11.6. We'll cover the upcoming GraphQL changes in a future blog.
    Deprecations
    Invision Community is a mature product, and some features and code that we added in the past no longer make sense, work correctly or are no longer appropriate for a modern platform running on well-maintained servers.
    You can see the upcoming deprecations in this topic. I suspect the biggest change will be removing the option to allow Display Names to form part of the authentication credentials when logging in, which is coming out in November.
    The other to watch for is the removal of the sockets fallback for when curl is not installed on the server or using a version older than 7.36. It's worth noting that curl 7.36 was released in March 2014 and now has hundreds of CVEs (known vulnerabilities) however, our techs still come across the odd server still using an older version. We will likely run AdminCP notifications to warn those affected of the upcoming socket fallback deprecation nearer the time, as it has no version attached. Just be mindful of this in your own apps if you use sockets directly for anything.
    You may also note that we've started adding deprecations to the release notes.
    As a reminder, we do not approve Marketplace submissions that restore functionality we've removed.
    That's it for September! Hopefully, it won't take too long to run through your apps and plugins. As always, comment here, or reach out via the forums if you need anything clarifying.
    Happy developing!
  13. Like
    SeNioR- reacted to Matt Finger for an entry, Development update for August 2022   
    Welcome to our August (and June and July) developer's Update!
    We've had a busy summer so far, with our team working on the final touches to 4.7 which introduced range of new Cloud specific features. In our August release we also added a way to schedule topics.
    @Jordan Miller announced the new solutions improvements here, this will be included in our September release (4.7.2)
    PHP8 Compatibility Scanner
    We are excited to announce that as a platform we (finally) are starting the process of migrating from PHP7 to PHP8 in order to keep the software secure, modern, and performant.
    Since PHP8 includes some breaking changes from PHP7, we've built a Method Scanner that will iterate through third party apps and plugins to find fatal issues, disabling any such customizations on upgrade. The apps and plugins disabled in this manner will not be able to be re-enabled until they are updated with the fixes. Developers, please make sure that your resources are fully tested with PHP 8+ and the method signatures match.
    For developers, the main issue the scanner looks for is instances in which a method's signature is altered when extending a class; this can cause fatal errors that make even the AdminCP inaccessible. Violating code can be found both in your hooks as well as other PHP classes your app/plugin uses. See the PHP8 Incompatible Apps and Plugins in the AdminCP Support Page to see exactly the issues identified and how to resolve:

     
    Pre-Upgrade Resource Checker
    We're also introducing a new AdminCP upgrade step to check installed resources for whether compatibility updates are available for version they're upgrading to.

     
    Here is the full changelog for our upcoming September release.
    Core - Added ACP Tool to scan all hooks to identify PHP8 fatal errors related to method overloading. - Added AdminCP new search terms to guide admins to the new areas. - Added a pre-upgrade Marketplace compatibility check. - Fixed an issue where a large number of profile field options can break the page layout on the member stats overview page. - Fixed an issue where members following an item may not be following the remaining item after a merge. - Fixed an issue where word filters could cause an item to be held for approval even if the author had more than the required number of posts to bypass. - Fixed an issue with hCaptcha where an incorrect language override could be requested. - Fixed an issue where it was possible to create an alert with forced reply from a moderator/admin account with a disabled messenger. - Fixed an issue where editing the ACP => System => Postings page with disabled registrations would throw an exception while the submission. - Fixed an issue where some alerts were not shown if they had an end date. - Fixed an issue where post to Twitter could potentially result in an uncaught exception - Fixed an issue where the oauth configuration page was missing the required css files. - Fixed an issue where a report title may appear in trending content (does not expose any sensitive data). - Fixed an issue where removing a manually added badge would not remove the badge - Fixed an issue where the rank progression chart may not work when non-default ranks are used. - Fixed an issue where the achievements rebuild may fail. - Fixed an issue where content tags from content created by the RSS Import feature could be associated with a guest account. - Fixed an issue where alerts could not be dismissed if they had long titles. - Fixed an issue where search options may break on profiles when status updates were disabled. Pages - Fixed an issue where orphaned categories could break syncing from topics. - Fixed an issue when using the REST API to fetch records where fields may not have the image lazyload removed. Forums - Added multiple improvements to "Mark as solution" including a re-engagement email, new UI to prompt authors to mark a reply as the solution and new stats. - Fixed an issue where the default forum views may not be used for guests. - Fixed an issue where soft deleted items may be archived and then subsequently deleted leaving orphaned reports. - Fixed an issue where a malformed findComment link caused a 404 error instead of loading the topic from the start. Commerce - Fixed a typo on the invoice settings page. - Fixed an issue on the credits page - Fixed an issue where deleting a subscription package would leave some orphaned data in the database. Changes affecting third-party developers and designers - Fixed an issue where plugin index.html files may get included as CSS causing a browser rendering issue.  
  14. Like
    SeNioR- reacted to Matt for an entry, Development update for May 2022   
    Welcome to our May developer's update!
    May has been a bit of a whirlwind as we worked through the cloud platform feature set along, the backlog of existing issues reported to us and a new feature coming to all platforms.
    Along with the usual bug fixes in the backlog, we also worked on a few popular requests, such as adding hCaptcha as a new CAPTCHA option. We've seen this battle spam bots much more effectively than the existing methods, so if you're being hit by a lot of spam, consider upgrading to 4.7.0 and enabling hCaptcha.
    Jordan announced the new alerts feature here. It's a new way to reach out to members (or entire groups) and ensure they read and act on the alert. Many configuration options make it a very flexible feature useful for one-off alerts to a single member. It can also be used as a welcome message as part of your onboarding process.
    Invision Community 4.7.0 (also known as the June release) will have tentative support for PHP 8.1. While we have tested the core apps extensively, you should check with any third party developers to ensure their apps are PHP 8 ready. We intend to move to PHP 8.0 as the minimum version later this year (and our dev team is excited about this, they can't wait to use mixed return types, which is as exciting as it gets for us most days).
    Here is the full change log for the June release.
    Core - Added alerts functionality. - Added hCaptcha support. - Added a setting to exclude groups from search logs. - Added support for PHP 8.1. - Increased minimum PHP version to 7.4 and recommended version to 8.0. - Added a solved/unsolved filter for activity streams. - Changed Marketplace search to 'AND' mode for more accurate results. - Changed 'member download' to output comma-separated values instead of tab-separated values to be consistent with member import. - Changed the poll behaviour to allow everybody to view the poll result of closed polls. - Improved the email editor to show the full email name while editing it. - Updated CKEditor to 4.19.0. - Moved the stream subscription links to an own menu item. - Fixed an issue that may prevent attaching audio files to content. - Fixed a minor typo in the forms.css template. - Fixed upload area not showing on minimized editors for guest users. - Fixed an issue where post counts were incremented even when a new item was held for approval via the profanity filters. - Fixed an issue where filters and sort options do not persist between deleting members in the Admin CP. - Fixed an issue where sitemap may show entries from offline applications. - Fixed an issue where support account may show as the latest registered member. - Fixed an issue where the upgrade process would fail to finish because of duplicate DB queries. - Fixed an issue where the default streams had a broken time period. - Fixed an issue where widgets may not be available even with enabled apps. - Fixed an issue where status updates where appearing as search results even if the user had no permissions to view profiles. - Fixed some issues with the online status indicator in account settings. - Fixed an issue with deleting bulletins when deleted remotely. - Fixed an issue where clicking on the reorder-menu link in clubs can add multiple reorder icons. - Fixed an issue where managing Widgets via the AdminCP > Applications > Dev Center meant that Yes/No toggles could fail to work. - Fixed an issue where the block submission filter failed to catch loose matches when in the middle of a word and/or using non latin characters. - Fixed an incorrect link on a modal popup when trying to follow a member when the member hasn't configured their preferences. - Fixed an issue fetching Clubs via the REST API when they have custom fields. - Fixed an issue when viewing a list of awarded badges if one was earned by a rule in a deleted application. - Fixed a missing `</ul>` in the poll template. - Fixed an issue where the 'approved content' notification (and any newly added notifications) might not have valid default options until edited via AdminCP. - Fixed missing padding on the AdminCP file locations modal. - Fixed some UX issues when revoking an OAuth access token. - Fixed an issue where non-image attachments inserted via the editor may not download. - Fixed a missing language string in member history when spam defense system applies moderation to a new member. - Fixed an issue with 'solved' push notifications linking to a non-existent page. - Fixed an issue with the Zapier Extension when PHP was running in CGI mode. - Fixed an issue where rank progress would still show in profiles when no ranks exist. - Fixed an issue using the ban filters in member group promotion rules. - The Editor Preview Button was removed from ACP Editors. - Removed the deprecated FX Country code from the Geolocation class. - Removed the ability to rebuild existing attachment thumbnails due to an incompatibility with content attributes required for lazy-loading. - Removed the SQL Toolbox. Forums - Improved the fluid-mode per forum filters to remove a page reload, and to reverse the filter checkbox status to make it clear which are being viewed. - Fixed an issue where checking an archived topic for new replies when you ignore other members may always show a 'new' post has been created. - Fixed an issue where top posters in the topic statistics section may show in the wrong order. Gallery - Fixed an issue with the followed Gallery Images page. - Fixed an issue with rebuilding thumbnails on legacy communities where the original image may no longer exist. Pages - Added the missing `__indefart_cms_page` language string. - Added copy buttons on the modal that displays the HTML to copy to embed blocks elsewhere. - Improved search indexing speed of comments when Elastic Search is used. - Fixed an issue where sorting by a numerical field could duplicate the option with an incorrect label. - Fixed issue with 'image upload' block carousels not working in the sidebar - Fixed an issue where custom Yes/No fields when used as a database filter were ignored when further sorting. - Fixed an issue where categories could have broken breadcrumbs. - Fixed an issue where entering a blank value for a required decimal field would save the value as 0. - Fixed an issue where using a Yes/No field as a database filter may cause the custom sort form display to not allow toggling of the Yes/No field. - Fixed an issue that allowed duplicate template group names in some circumstances. - Fixed an issue where who's online widget blocks would throw an error while creating or editing them in the ACP. Converters - Fixed an issue rebuilding some profile photo images. - Fixed an issue where vBulletin `[video]` tags would not be parsed if the video ID contained a hyphen. Commerce - Added ability to require an active subscription to use community. - Added support for Stripe - Apple Pay Domain Verification Files on Cloud. - Improved Subscriptions including up/downgrading to other subscriptions and offering limited free subscriptions. - Improved performance when updating a large number of existing purchases. - Removed deprecated Amex Express checkout options. - Fixed some issues that can occur when requiring a subscription or product to be purchased during registration. - Fixed an issue where a card would not be auto-billed if the customer did not have an address. - Fixed a niche issue where a renewal invoice (for manual payment) would not be generated if a PayPal Subscription was cancelled on an active purchase. - Fixed an issue where account credit would not be used for an invoice if the credit remaining was the exact value of the invoice. - Fixed an issue calculating the next renewal date when upgrading between Subscriptions that may use a different renewal period (i.e. monthly vs annually). Calendar - Fixed an issue where the day view wouldn't show todays events when it's being used as the default calendar view. Downloads - Fixed an issue where change logs may show the wrong published date if the file description had been edited since the last update. - Fixed an issue where creating a downloads category with the "Keep previous versions?" Setting being disabled would result in a DB error. Platform - Added real time and historic trending data in sidebar blocks and leaderboard. REST, Webhooks and Zapier - Fixed an issue where the 'hidden' content item filter would be ignored for any content type except topics. - Fixed an issue where the date parameter for the 'Edit a topic' endpoint was not updating topic/post post date. Key points for developers are as follows:
    Added PHP 8.1 support; however, we have silenced deprecation errors for core applications and system directory as we work through those in the following releases. Updated Whoops to 2.14.5 Fixed an issue where managing MFA in the Account Settings would result in an IN_DEV CSRF key warning. Fixed an issue where you could not pass variables to the {hextorgb} theme plugin. Fixed an issue where creating or editing a forum with IN_DEV being enabled would return an error. Fixed an issue with ips.ui.infiniteScroll.js when using FURLs. Fixed a syntax error in the core unsubscribeStream.txt email template. Member filters will only be processed/visible for group promotions if they have a matches() method. That's it for now; see you on the forums!
  15. Like
    SeNioR- reacted to Matt for an entry, Development update for April 2022   
    Welcome to our April developer's update!
    This month has seen the developers work on a variety of features coming to our cloud platform, some of which we've been testing here, which include real-time updates on what members are viewing and when they are typing replies and an image scanner which not only identifies what is in the image, it also tags it for search results. Furthermore it can also hold images for moderation if they contain nudity, etc. We've got more to come and will announce them as they are finished.
    The cloud platform features leverage multiple technologies such as node, JWT security, and AWS specific functionality, enabling us to build pretty impressive new features quickly. As we expect more sophistication and algorithmic crunching from our web apps, we're starting to break out of the PHP and MySQL limitations to deliver forward-thinking features.
    Of course, we have plenty of new features coming to all platforms, including the self-hosting version; I can talk about a few changes we've made but let's start with some housekeeping.
    There will not be a full release for May, although we will be releasing several betas throughout the month. We are taking this time to finalise a few bigger changes to our codebase.
    For those running their own servers, we are updating the minimum PHP requirement to 7.4 and the recommended version to 8.0. If you're not sure which version you currently use, now is a good time to check!
    We are working on PHP 8.1 compatibility still and are aiming to have that finished for June's release.
    The list of fixes already in the June release is as follows:
    Core - Fixed an issue that may prevent attaching audio files to content. - Fixed a minor typo in the forms.css template. - Fixed upload area not showing on minimised editors for guest users. - Fixed an issue where post counts were incremented even when a new item was held for approval via the profanity filters. - Fixed an issue where filters and sort options do not persist between deleting members in the Admin CP. - Fixed an issue where sitemap may show entries from offline applications. - Fixed an issue where support account may show as the latest registered member. - The Editor Preview Button was removed from ACP Editors. - Removed the deprecated FX Country code from the Geolocation class. - Removed the ability to rebuild existing attachment thumbnails due to an incompatibility with content attributes required for lazy-loading. Gallery - Fixed an issue with the followed Gallery Images page. - Fixed an issue with rebuilding thumbnails on legacy communities where the original image may no longer exist. Pages - Added the missing `__indefart_cms_page` language string. - Fixed an issue where sorting by a numerical field could duplicate the option with an incorrect label. - Fixed issue with 'image upload' block carousels not working in the sidebar - Fixed an issue where custom Yes/No fields, when used as a database filter, were ignored when further sorting. Converters - Fixed an issue rebuilding some profile photo images. Commerce - Improved performance when updating a large number of existing purchases. - Removed deprecated Amex Express checkout options. - Fixed a niche issue where a renewal invoice (for manual payment) would not be generated if a PayPal Subscription was cancelled on an active purchase. Calendar - Fixed an issue where the day view wouldn't show today's events when it's being used as the default calendar view. A few items still being finished before being sent for peer review include tweaks to search logging. Andy added the ability to specify which groups to log anonymous search sessions. We got some feedback that bot searches were polluting the results, making it hard to discern search trends from members over time. As we anonymise the search data, we can't pick out specific member groups once it's been written. Andy also moved the search logs to their own page to reduce confusion over what the data represents.
    Andy has also been working on some activity stream improvements to bring a "Solved/Unsolved" filter option to allow you and your members to find unsolved (or indeed solved) topics quickly. This will require a search index rebuild after upgrading.
    You may also find a few new hook points added, which are in the following locations:
    \IPS\Helpers\Form\Upload::populateTempData()
    This is called from within processUploads and allows you to modify the data before it is saved into core_files_temp.
    \IPS\applications\forums\modules\front\forums\topic::finishManage()
    This is called during manage() and allows you to modify the $topic before it is returned to \IPS\Content\Controller. If you have to overload manage() in your apps, you may find this a better hook point.
    \IPS\Content\Search\Index\indexData now allows $content modification before it is stored via an extension in /applications/{app}/extensions/core/SearchIndex
    That's it for this month!
×
×
  • Create New...