Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


 Content Type 


Release Notes

IPS4 Guides

IPS4 Developer Documentation

Invision Community Blog

Development Blog

Deprecation Tracker

Providers Directory


Release Notes v5





Everything posted by Matt

  1. Matt

    Profile Spam?

    Already a feature when editing a member group.
  2. The answer is possibly if you mean the last round of betas designed for 3.0.0. I can't see any reason why not. We've just not tried.
  3. Like everything in IPB 3.0, the subscriptions manager is a separate application. We can release it at anytime without requiring a new version of IP.Board 3.
  4. Thank you for you compliment. We're happy to allow all current license holders with download access have IP.Board 3 at no extra cost. I'm sure that if our accountants ran the numbers, they'd tell us to reconsider. We promised that there would be no extra charge for the upgrade to 3 and we'll stick by that. :)
  5. Meanies! It used Ajax. And Ajax was cool. We were the first to use it on a bulletin board and that was the best I could do. :(
  6. It's a bit of a limitation, I believe that the text editor needs focus to complete setting up design mode.
  7. Hey! I worked really really hard on that!!
  8. Oh dear.. are we doing this again?
  9. It would be pointless to release RC1 if we still have stuff to fix. RC 1 is when we consider it 'done'.
  10. You can restrict the number of characters allowed in the topic title in your ACP settings. We've left ours deliberately long.
  11. Thanks guys, go nuts and test it out as much as you can. Please don't be alarmed if we seem to take a minor step back with some stuff, I've fiddled with a few things, mostly: Topic MarkingCSS CachingMemory DebuggingSo let me know if you see anything odd with any of that.
  12. You won't need too. Our DB is not UTF-8 and we're using them just fine.
  13. Just a note: I've added back the basic character conversion tables which only take up about 200k space, uncompressed. I will write a function to check your character set and test for local conversion methods before checking if you need to download more tables.
  14. Matt

    IPB3 Beta 4

    I have turned off JSDebug in the templates. Let us know if this fixes the issue. :)
  15. Matt

    IPB3 Beta 4

    I was going to ask that too.
  16. Matt

    IPB3 Beta 4

    I am using FF 3.1 beta 3 and I can reproduce the edit bug, so I'll file a bug which was all that was needed in the first place. It seems that the ajax function isn't being fired for some reason. As we use prototype heavily, I'll check there first as there may be a bug with Prototype or change required.
  17. Matt

    IPB3 Beta 4

    I chose not to comment on the comparison between us and Mozilla because it's like comparing apples to fish.
  18. Matt

    IPB3 Beta 4

    Isn't a little premature to dump all your past purchases on the strength of a beta release of a future version not working with cutting edge alpha / beta versions of web browsers? The current version (2.3.6) is very stable and that's the supported version. We know that IP.Board 3.0.0 Beta has issues; that's the very reason we ask you to test it. We would not ask you to test it if you were going to make a decision whether to continue using IPS products on the strength of it. Now, does the edit button work for you in FF 3.0.7? Forget 3.1 Beta 3.5 beta, etc - just use the current stable FF release and let us know. If it does not, then file a bug report. That's all we ask. Lee, Sunrise was telling you that the option to include the full reply in a topic subscription notification has been in IP.Board for years, since 2.1 if I remember correctly. This feature is also in IP.Board 3.0.0 so there is no need for a mod, etc.
  19. Since we unveiled the new friendly url feature on our preview board, we have received a lot of feedback on how it could be improved with regards to maintaining good search engine optimization (SEO). Every feature we add has to be weighed against the impact to efficiency and memory usage. We understand that not every customer has the luxury of a dedicated server. We want to ensure the very best experience for a wide variety of hosting environments. However, in this case we felt we could make some improvements to the friendly url feature without compromising efficiency. The new settings can add some small overhead, but we felt that those who wanted the very best optimized content would accept that. Meta Tags I have added a way to add meta tags to the final content through: $this->registry->output->addMetaTag( 'name', 'content' ); This is used internally to add a meta tag for 'indentifier-url' and 'description'. The description is the first post of a topic; a forum description or the user's "About Me" information using the signature if no "About Me" information is present. You can use this interface in your own code to add more tags if desired. Robots.txt A primary concern for those interested in SEO is duplicate content. There are many ways to access a single topic due to the different variables that are used; pagination and search strings are a few examples. To help limit the duplicate pages indexed, IP.Board now ships with an example "robots.txt" file for you to edit and upload to your root directory. Redirecting 'old style' links Another concern was that the old style links, for example: index.php?showtopic=10, are still able to access pages. This is necessary so that you do not lose bookmarks or traffic from currently indexed links. You can now choose to redirect with an optional "301 Moved Permanently" header to the new link format. This is transparent to the end user but will help search engines locate the correct copy of your content. Incorrect Permalink Handling The new friendly URLs are often based on user generated content. For example, a topic called "My Great Topic" will have the permalink "/topic/10/my-great-topic/". Now, when this topic title is edited, the permalink will change too. For this reason IP.Board allowed access to the topic as long as the topic ID was present, so all of the following links resulted in the same topic being shown: /topic/10/my-great-topic/ /topic/10/my-edited-topic-title/ /topic/10/ /topic/10/i-just-made-this-up/ The downside to this is that some may consider this duplicate content. You can now opt to redirect with a "301 Moved Permanently" header to the correct permalink. This again is transparent to the end user but it will help search engines locate the correct copy to index. You can also opt for IP.Board to simply add a 'robots' meta tag with the value 'noindex' if you do not wish to redirect. This will tell the search engine to not index that URL. We hope that these improvements will be seen as a good first step in basic SEO without impacting performance.
  20. Matt

    Member Map for 3.0?

    I can categorically state that this will not be making an appearance in IP.Board 3.0.0.
  21. Since IP.Board 2, we've had a "kernel" of classes which IP.Board uses but do not depend on IP.Board to use. A selection of these kernel classes includes DB management, file uploads, emailing, RSS parsing and reading, XML parsing and reading and our proprietry archive format XMLArchive. For example, you could use "classUpload.php" and "classImage.php" in your own modifications or extensions to handle uploads and GD thumbnail generation. You would not have to initialize the registry or do anything else other than just include the file and use it. As we took the plunge and went ahead with making PHP 5 a requirement, we were able to make some long-awaited improvements. Here are the high-lights. Custom Fields Josh has completely re-written custom field handling within IP.Board and this class ties it altogether. Josh uses just about every PHP 5 trick in the book including abstract classes, interfaces and ArrayAccess to provide a simple clean interface that can be used in almost any project. It doesn't have to be limited to just IP.Board's custom profile fields. Graphing Remco has extended this class to include many new graph types including "funnel", "bubble" and "radar" graphs so that presenting data is more relevant. As IP.Board 3.0.0 develops, we'll be making good use of these new methods for statistic reporting within the ACP. GD and ImageMagick Brandon virtually started from scratch with our GD image creation. He also wrote a class for imagemagick offering more choice for those who have it installed. It's now very simple to resize an image or add a watermark. $image->init( array( 'image_path' => "/path/to/images/", 'image_file' => "image_filename.jpg" ) ); //Set max width and height $image->resizeImage( 600, 480 ); // Add a watermark $image->addWatermark( "/path/to/watermark/trans.png" ); $image->displayImage(); $image = new classImageGd(); XML Parsing and Creating We've had a class for XML parsing and creating since IP.Board 2 but it was a kludge of PHPs then primative XML handling extension and a hand-rolled class for when the XML engine wasn't available. These methods functioned well but were known to be memory intensive. Thankfully, PHP 5 has much better native XML handling which I took full advantage of when rewriting this class. I looked at simpleXML intially but found it too, well, simple for our needs so I went ahead and used the full DOM methods. This gives us full control over both reading and creating XML documents. Here's how simple it is to create a new XML document: $xml->newXMLDocument(); /* Create a root element */ $xml->addElement( 'productlist', '', array( 'name' => 'myname', 'version' => '1.0' ) ); /* Add a child.... */ $xml->addElement( 'productgroup', 'productlist', array( 'name' => 'thisgroup' ) ); $xml->addElementAsRecord( 'productgroup', array( 'product', array( 'id' => '1.0' ) ), array( 'description' => array( 'This is a description' ), 'title' => array( 'Baked Beans' ), 'room' => array( '103', array( 'store' => 1 ) ) ) ); $xml->addElementAsRecord( 'productgroup', array( 'product', array( 'id' => '2.0' ) ), array( 'description' => array( 'This is another description' ), 'title' => array( 'Green Beans' ), 'room' => array( '104', array( 'store' => 2 ) ) ) ); $xmlData = $xml->fetchDocument(); $xml = new classXML( 'utf-8' ); This will produce this document: <productgroup name="thisgroup"> <product id="1.0"> <description>This is a description</description> <title>Baked Beans</title> <room store="1">103</room> </product> <product id="2.0"> <description>This is another description</description> <title>Green Beans</title> <room store="2">104</room> </product> </productgroup> </productlist> <productlist name="myname" version="1.0"> This is how you'd parse that document: /* Grabbing specific data values from all 'products'... */ foreach( $xml->fetchElements('product') as $products ) { print $xml->fetchItem( $products, 'title' ) . "\"; } /* Prints: */ Baked Beans Green Beans $xml->loadXML( $xmlData ); I'm sure you can appreciate how simple it is to use these new XML features! XMLArchive I created our XMLArchive format for IP.Board as a way of combining several files into one without using tar or zip which can be troublesome on some servers. XMLArchive is very simply file data in a basic XML format. I rewrote the class to make it easier to use and to add more functionality. Here's how to read an archive: $archive->read( "/path/to/archive.xml" ); print $archive['someDir/file.html']; $archive = new classXMLArchive(); As you can see, we use PHPs ArrayAccess to transparently allow access to the contents of the fileset from the main class handle. Here's how to create an archive: $archive->add( "someDir" ); $archive->add( "anotherDir/anotherFile.html" ); $archive->add( "Create a new file from scratch!", "anotherDir/brandNewFile.html" ); # Save gzipped $archive->saveGZIP( "/path/to/archive.xml.gzip" ); # Save normally $archive->save( "/path/to/archive.xml" ); # Just return the data $archive->getArchiveContents(); $archive = new classXMLArchive(); For simplicity's sake, there is now just one interface to add files: "add()". Personally, the fewer function names to remember the better! Naturally, this blog entry does not cover all the changes and improvements within the kernel classes but it does go some way to showing just how much energy we've invested in ensuring that IP.Board is as robust and efficient as it can be.
  22. Brandon blogged a while back about IP.Board's integration points. I wanted to spend a moment discussing the features within IP.Board 3 that all you integrate the board with your website and to create your own network. Member Management Since IP.Board 2, we've had, what we call, "Log In Modules". This is basically a mini-framework to allow custom code to be used easily when authenticating and registering members. For example, if you had a database full of members and you wanted for them to be able to use their existing usernames and passwords, you could add a log in module to query your database or other system (via SOAP, XML-RPC, etc) for authentication. This system has been enhanced based on user feedback and IP.Board now ships with modules for LDAP and OpenID which will make it much easier to use existing authentication. Networking The log in modules also tie into our 'IP.Converge' product which allows you to share authentication details across multiple IP.Board installations. The IP.Boards don't even need to be on the same server! In fact, we use Converge and the log in modules ourselves so that our customers can use the same log in details on the forum as they do in our ticket center. You could use this functionality to share members across many forums, creating a true network of members. Using the IP.Board Engine We've made no secret that IP.Board 3 is a complete rewrite. The new framework makes full use of PHP 5 and incorporates many timesaving features that you can instantly make use of. It's common for our customers to ask how they can use certain parts of IP.Board within their own website. For example, they'd like to show a list of recent topics or posts. That's no problem as we've had an API class interface since IP.Board 2. However, if you wanted to send data to IP.Board, such as a new post or new personal message; things got tricky. Even using a template bit required a lot of code copying. For example, if you wanted to make use of our database engine or templating engine, you would need to copy a lot of 'index.php' so that it set up ipsclass correctly. With IP.Board 3, that is no longer required. You can use our engine in your own scripts as simply as this: require_once( IPS_ROOT_PATH . 'sources/base/ipsRegistry.php' ); $registry = ipsRegistry::instance(); $registry->init(); require_once( './initdata.php' ); Those few lines of code give you access to: Caches, settings, member management, database management and more. Writing your own code Quite often, you want to add some IP.Board functionality to your own website. With IP.Board 3.0.0 it's very simple. You want to add a new post? No problem, simply use that code above and add: $postClass = new classPostForms( $registry ); $postClass->setForumID( $forumID ); $postClass->setForumData( $this->registry->class_forums->forum_by_id[ $forumID ] ); $postClass->setTopicTitle( "My Topic" ) $postClass->setPostContent( "Hello, I am post content!" ); $postClass->setAuthor( $memberID ); try { $postClass->addTopic(); } catch( Exception $error ) { print $error->getMessage(); } require_once( IPSLib::getAppDir( 'forums' ) . '/sources/classes/post/classPost.php' ); It's really as simple as that! Note the try -> catch block? That's consistent with all the new API-like functions. We take advantage of the PHP 5 exception handler to return information on what went wrong. We also list all the possible exceptions that are returnable in the phpDoc for that function. Of course, seasoned modification authors will already be familiar with functions similar to those present in IP.Board 2's API system. The good news here is that this functionality doesn't require an API bridge anymore, it's the exact same code that is used in the normal posting routines. Do you want to send a new personal conversation to someone in your own code? Simple! $messengerFunctions = new messengerFunctions( $registry ); $messengerFunctions->sendNewPersonalTopic( $toMemberID, $fromMemberID, $invitedUserIDArray, $msgTitle, $msgContent ); require_once( IPSLib::getAppDir( 'members' ) . '/sources/classes/messaging/messengerFunctions.php' ); Want to get a list of PMs in your own code? $messengerFunctions = new messengerFunctions( $registry ); $messengerFunctions->getPersonalTopicsList( $memberID, 'in' ); require_once( IPSLib::getAppDir( 'members' ) . '/sources/classes/messaging/messengerFunctions.php' ); Another common request is to use IP.Board's templates in your own projects, again this is as simple as: require_once( IPS_ROOT_PATH . 'sources/base/ipsRegistry.php' ); $registry = ipsRegistry::instance(); $registry->init(); print $registry->output->getTemplate( $templateGroup )->templateName( $templateArguments); require_once( './initdata.php' ); There really is so much that you can do. Listing them all would make for a very large blog entry indeed! We will of course be providing a lot of documentation on these new features. Combine this functionality with the new hooks and plug-ins system and you've got a very quick way to build new code using our core. We're very excited to see what you do with it!
  23. Around ten years ago, I was hard at work on one of the first 'Private Message' modifications for a board that has long ceased to exist. At the time it was an exciting novelty to be able to message another board member. These days it's an expected feature for any seriously considered forum software. Not much has really changed with messaging's core features. Sure, the interface has become a little smarter and there have been a few little bells and whistles added such as message tracking but ultimately it's still sort-of email based in functionality. This was a limitation I noted when developing IP.Dynamic. In fact, almost two years ago, I blogged about Personal Topics, the next logical step in private messaging. Enter Personal Conversations As, with most of IP.Board 3.0.0's new features, personal conversations - as we like to call them - have been a popular request. A request that we have now fulfilled! Why bother CC-ing and forwarding messages to other members when you can invite them right into the conversation? How it Works Where you would normally 'compose' a new message, you now 'start a new conversation'. The form looks largely the same. However, instead of there being a space to "CC" other members, there are boxes for you to invite other members. How many members you can invite is up to the administrator as it's limited to your group settings. In fact, the admin could remove your ability to invite other members completely if they desired to return to a more traditional messaging system. The recipient and each invited member will be notified they have a new message (in terms of notification, a message is either a new conversation or a reply to any existing conversation). The new conversation will appear in both their "Inbox" and their "New" folders. It will remain in their "new" folder until its read and then it will only be available in the inbox. Why? Well, because of the magic folders. But more of that in a moment. The conversation looks largely the same as a normal topic does; linearly sorted with the newest replies last. There is even a "fast reply" form much like you use when replying to topics. This instantly makes it easier to view previous replies and keep the 'thread' of conversation without having to delving into your 'sent' folder to see what you replied with. The topic starter (and any participating super moderator) can choose to 'block' any participant that is blockable. Immunity from being blocked is granted by the "Not Ignorable" setting. This means you can ensure that you (the admin) can never be blocked from a conversation you are participating in. When a participant is blocked, the topic vanishes from their folders until they are unblocked. Each participant apart from the topic starter can choose to leave a conversation at any time. Once the participant has left the conversation, it is only available in the magic "Finished" folder and the replies no longer count towards your space allowance. The topic starter cannot re-invite you but you can choose to rejoin the conversation at any time. The topic starter can choose to invite more members (up to their invite allowance) at any time from the conversation display screen. Each participant can also view all participants and see the last time they read the conversation. Magic Folders This is the term we give to certain folders that are not editable or removable. They are: "New", "Finished", "All" and "My Conversations". Topics in "New" and "My Conversations" can also be in other folders. "My Conversations" is the default location for any conversation you start. You can then move into another folder -- but it will always be accessible from "My Conversations". "New" simply lists any new personal conversations or any personal conversations with new replies. So, you could have a conversation in "My Folder". When it receives a new reply, it will also be listed in "New" until you read it. "Finished" simply lists all the conversations you've left, allowing you to rejoin if desired. "All", as the name implies, lists all the conversations you are participating in as either a starter, recipient or invitee. We think this is a very exciting step forward for personal communication and opens up new ways to communicate via the forum. Ten years is a long time to wait for change. We hope you find it worth the wait!
  24. Possibly the most often requested feature we've had since the very first version of IP.Board is 'friendly URLs'. Although this sounds like you'd expect your URLs to greet you with a self-empowerment phrase first thing in the morning, it really relates to making the board generated URLs a little more attractive to both humans and search engines. I am being very careful to avoid the phrase "Search Engine Optimization" in this opening few paragraphs despite it being used often in the request for friendly URLs. What we've added will definitely help with SEO but it's not a complete solution and neither is it intended to be. So, what do you have? In a nutshell: friendly URLs! The process to create and manage them is far more interesting than the end result, but more on that in a moment. Lets first look at some examples of the new URLs. Here's a few sample URLs from IPB 2.3.x: To show a forum (My Test Forum): www.board.com/forums/index.php?showforum=10 To show a topic (My Test Topic): www.board.com/forums/index.php?showtopic=99 To show a user (Matt Mecham): www.board.com/forums/index.php?showuser=30 There's nothing wrong with those URLs. They are short and concise and they spider very well, but we can do a little better to make them more attractive. If you are on a Windows webserver, you can use the 'query' string method which presents URLs like this: www.board.com/forums/index.php?/forum/10/my-test-forum www.board.com/forums/index.php?/topic/99/my-test-topic www.board.com/forums/index.php?/user/30/matt-mecham If you are on an apache based web server you can make use of the 'path_info' method: www.board.com/forums/index.php/forum/10/my-test-forum www.board.com/forums/index.php/topic/99/my-test-topic www.board.com/forums/index.php/user/30/matt-mecham Even better, if you can manage your own .htaccess files, you can make use of the mod_rewrite functionality. For convenience, the mod_rewrite code is generated for you. The end result looks like this: www.board.com/forums/forum/10/my-test-forum www.board.com/forums/topic/99/my-test-topic www.board.com/forums/user/30/matt-mecham What would happen if you used accented characters like this: M
  25. Topic markers have evolved quite a bit over the past few years. What started out as being an almost secondary concern has become quite an important part of the user experience. A Very Brief History Early versions of IP.Board relied on cookies to track read topics. This worked fairly well but it wasn't without problems. Anything to do with cookies is always a little flaky. There is a very finite amount of information you can store and browsers have a habit of eating them or not setting them correctly. The biggest complaint, however, is that topics that you have read on one computer do not stay read on another computer. IP.Board 2 introduced topic markers that are stored in a database table. This greatly increased stability and allowed the read topics to remain read regardless of computer used. However, this did lead to some performance issues on busier boards as the topic marker table is often in demand whcih can result in locking issues and processes queueing. Also, the code wasn't centralized and sprawled through different files making maintenance very difficult. Learning From Experience It was obvious we needed to centralize all the code and create a common, simple public interface as a matter of course. We also wanted to allow our other applications (such as blog and gallery) to use this system without having to copy code. Making it truly extensible also allows modification authors to use this centralized system without having to maintain their own code. Next up was the performance issue. How could we increase performance without losing functionality? The most obvious answer was to store the read topics in the user's session. This was fine in principle but there were obstacles to overcome. First of all, session handling in IP.Board 2 is not entirely centralized. There is a class but it is not used exclusively. Other files such as register.php and login.php are allowed to modify the session table without telling other classes what it did. When you're trying to preserve data, this cannot be allowed. Also, session handling in general isn't an exact science. IP addresses change meaning new sessions can be created several times during a single visit. The solution to these problems must be robust, centralized and extensible. So, what's new? First up was tightening up session handling. All session management is now performed through a single class (publicSessions). Other files that need to manage sessions are done so via publicSessions. This allows this one class to keep tight control over the session data. The biggest challenge was to allow sessions to handle the marker data and only allowing the markers to be written back to the database table when the session is deleted. The theory is sound and simple but the execution a little trickier. The gory details of which are explained a littler further down for the technically minded. In brief, the system loads the markers from the database table when a new member session is created. The markers are saved in with the rest of the session data when the session is updated at the end of a page view (to update the running time and location, etc). This continues until the session is due to be removed, for example, when the member is no longer active and the session is older than the allowed time. The sessions to be removed are captured and allowed to be examined by other classes. The item marking class examines these sessions and writes back the marker information to the marker database. The system also makes use of cookies to give some permanence for guests and those that are not logged in. The cookies are limited to the last 100 items read to prevent cookies being sent that are too large. The end result is a much leaner system which should be much more efficient and presents a very simple public interface. Here's some sample code to give you a taste: $itemMarking->markRead( array( 'forumID' => 2, 'topicID' => 10 ) ); # To fetch the read status of an item if ( $itemMarking->isRead( array( 'forumID' => 2, 'itemID' => 99, 'itemLastUpdate' => 1200098989 ) ) === TRUE ) { .... } # To fetch the last time an item was marked $lastMarked = $itemmarking->fetchTimeLastMarked( array( 'forumID' => 2, 'itemID' => 99 ) ); # To mark an item read (an item is a topic for the forums 'application') Modification authors can write their own plug-ins and make use of the system with minimal coding effort. Listen Up, Here Comes The Science Bit For the more technically minded, this section explains how the system works within the new IP.Board 3.0.0 framework. The first challenge was to make proper use of __construct and __destruct within PHP 5. This is very straightforward in the case of __construct; this is run when the class is initialized. There are no problems with that. The item marking class grabs and filters the cookie data and also grabs and filters the session item marking data in __construct. The real issue is with __destruct. Specifically the order in which they are called. In PHP 5.0.0 to PHP 5.2.4 they are called in the order they were created. This means that by the time __destruct() is called in item Marking the DB connection has been closed which isn't at all helpful. This is because the DB is set up before classItemMarking. Now, as of PHP 5.2.5 the __destruct order has been reversed. This means that the DB connection will still be available. However, that's not very convenient for code that has to be robust on different platforms and with unpredictable version of PHP. Another solution was needed. Thankfully register_shutdown_function() executes before any __destruct() calls, so we can reliably use this. There is a __myDestruct function in the ipsRegistry class which calls __myDestruct() in all the registry child classes (DB, Member, Request, Cache, Settings, etc). The member registry class makes use of this to fire a manual destruct function within itemMarking to allow it to save back any data for deleted sessions and to provide information for the session update. A __myDestruct fires within the public session class to actually update the sessions and delete the expired ones. Phew! As you can see, there's a lot going on behind the scenes in IP.Board 3.0.0 which makes full use of all PHP 5 has to offer.
  • Create New...