{"id":32,"date":"2015-04-12T19:59:24","date_gmt":"2015-04-12T17:59:24","guid":{"rendered":"https:\/\/daniel.liljeberg.io\/?p=32"},"modified":"2021-04-01T22:02:08","modified_gmt":"2021-04-01T20:02:08","slug":"streamlining-accelerating-and-encapsulating-osclass-plugin-development","status":"publish","type":"post","link":"https:\/\/daniel.liljeberg.io\/sv\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/","title":{"rendered":"Streamlining, accelerating and encapsulating Osclass plugin development"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">In our\u00a0<a href=\"http:\/\/daniel.liljeberg.io\/2015\/04\/12\/how-to-develop-plugins-for-osclass\/\" target=\"_blank\" rel=\"noreferrer noopener\">previous post<\/a>\u00a0we looked at the basics of building a plugin for Osclass. There are however quite a few issues that I have observed in almost every plugin I have looked at that I felt I wanted to do differently.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Issues I saw with plugins<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>index.php often becomes bloated with functions that handle every aspect of the plugin. At rare occasions are classes that separate&nbsp;logic and presentation introduced (I did this myself when usign the&nbsp;<em>official<\/em>&nbsp;way of constructing plugins), but more often than not&nbsp;index.php will just consist of a myriad of function mixing logic and presentation, acting as functions for hooks and so on and so fourth.<\/li><li>All functions in index.php&nbsp;are publicly available. That means that for plugins that ended up having all their function in index.php, any one of these functions would be publicly available to call from&nbsp;any other plugin.<\/li><li>More often than not hooks will be riddled with&nbsp;<strong>html code<\/strong>,&nbsp;<strong>javascript&nbsp;<\/strong>together with&nbsp;<strong>switch<\/strong>&nbsp;and&nbsp;<strong>if statements<\/strong>.<\/li><li>Plugins are not naturaly object oriented.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Now, you can solve a lot of these issues on your own and some things are not even problems to some people. Object Oriented development might not be your cup of tea and in that case you will not have the same issues I have with this. But to me Object Oriented development is a great way to encapsulate functionality. For instance for a Plugin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I have for example introduced classes that actually handle my logic and presentation that were basically just called from the hooks in my plugin. But as time went on and I noticed I did more than the few plugins I originally thought I would be doing I felt I wanted some base for my plugins and not reinvent the wheel every time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Streamlining, accelerating and encapsulating Osclass plugin development<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I decided to build myself a base library that I could use to quickly create new plugins.&nbsp;I created&nbsp;<strong>dliCore<\/strong>&nbsp;which consists of two components. It\u2019s all just a few days old so things could change, but here\u2019s some of the basics of what I want to achieve.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">dliCore<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">dliCore is a plugin in itself. It provides admin interfaces to configure common things that all plugins based on dliCore can take advantage off.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Configuring things like caching manager<\/li><li>Presents common place for support requests regarding plugins built using dliCore<\/li><li>Contains dliLib and makes sure that is available to plugins<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">dliLib<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li>Contains a myriad of classes to support development of plugins<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Together they present developers with a base that accelerates development of plugins and keep them organized even when they grow to large proportions. Do note that any part of it is optional. There are functionality to link objects to specific database tables, but a developer is free to create an Osclass DAO object and work with that if they want to.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This was primarily meant for my own plugins and could function as a catalyst for others to create their own solutions. But if there is a&nbsp;desire for others to use this I\u2019m open to a public supported release to help all of my fellow plugin developers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Building our Osclass&nbsp;<em>Hello World<\/em>&nbsp;plugin using dliCore<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With&nbsp;<strong>dliCore<\/strong>&nbsp;I wanted to take a more object oriented approach and encapsulate plugins in a more clear manner. Instead of having your&nbsp;<strong>index.php<\/strong>&nbsp;file contain a bunch of public functions, all which are loaded, mixed logic and presentation within these functions etc.&nbsp;<strong>dliCore<\/strong>&nbsp;allow you to encapsulate all of your plugin functionality within a&nbsp;<strong>Plugin<\/strong>&nbsp;object. This makes the&nbsp;<strong>index.php<\/strong>&nbsp;file look a bit different.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace dliTest;\n\/*\nPlugin Name: dliTest\nPlugin URI: http:\/\/www.osclass.org\/\nDescription: Test plugin to test functionality of dliCore\nVersion: 0.1.0\nAuthor: Daniel Liljeberg\nAuthor URI: http:\/\/www.danielliljeberg.se\/\nShort Name: dliTest\nPlugin update URI: dliTest\n*\/\nuse dliLib\\Plugin\\Manager\\PluginManager;\nuse dliTest\\dliTestPlugin;\n \nif(osc_plugin_is_enabled('dliCore\/index.php')) {\n  require_once(osc_plugins_path() . 'dliCore\/index.php');\n  \\dliCore\\dliCore_createAutoloader(__NAMESPACE__, osc_plugins_path());\n  $plugin = new dliTestPlugin();\n  PluginManager::getInstance()->registerPlugin($plugin);\n}\nelse {\n  function dliTest_install() {\n    die(\"This plugin requires dliCore to function!\");\n  }\n  osc_register_plugin(osc_plugin_path(__FILE__) . '_install', 'dliTest\\dliTest_install');\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">First we define a namespace for our plugin. These further help us keep our plugin specific code isolated.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">namespace dliTest;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A good convention is to have the name of your&nbsp;<strong>plugins folder<\/strong>, the&nbsp;<strong>namespace<\/strong>&nbsp;and the&nbsp;<strong>name of the plugin<\/strong>&nbsp;be the same.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After that we have our normal&nbsp;<strong>info<\/strong>&nbsp;block.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\nPlugin Name: dliTest\nPlugin URI: http:\/\/www.osclass.org\/\nDescription: Test plugin to test functionality of dliCore\nVersion: 0.1.0\nAuthor: Daniel Liljeberg\nAuthor URI: http:\/\/www.danielliljeberg.se\/\nShort Name: dliTest\nPlugin update URI: dliTest\n*\/<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">I would have liked to be able to include this in the plugin class itself, but due to how Osclass reads that data it\u2019s not possible. I wanted to make sure no alterations were needed to Osclass in order for dliCore to work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Next we declare that we will be using the&nbsp;<strong>PluginManager<\/strong>&nbsp;and our plugin&nbsp;<strong>dliTestPlugin<\/strong>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">use dliLib\\Plugin\\Manager\\PluginManager;\nuse dliTest\\dliTestPlugin;<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After that we check that&nbsp;<strong>dliCore<\/strong>&nbsp;is enabled. If it is we make sure that the&nbsp;<strong>index.php<\/strong>&nbsp;file of&nbsp;<strong>dliCore<\/strong>&nbsp;is loaded by a&nbsp;<em>require_once<\/em>&nbsp;(since we can\u2019t force Osclass to load that before any other plugin) create an instance of our plugin and register it with the&nbsp;<strong>PluginManager<\/strong>. If dliCore is not enable we register a&nbsp;<em>install hook<\/em>&nbsp;that will just tell the user that&nbsp;<strong>dliCore<\/strong>&nbsp;is needed for this plugin to work.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">if(osc_plugin_is_enabled('dliCore\/index.php')) {\n\nrequire_once(osc_plugins_path() . 'dliCore\/index.php');\n\\dliCore\\dliCore_createAutoloader(__NAMESPACE__, osc_plugins_path());\n$plugin = new dliTestPlugin();\nPluginManager::getInstance()->registerPlugin($plugin);\n}\nelse {\nfunction dliTest_install() {\ndie(\"This plugin requires dliCore to function!\");\n}\nosc_register_plugin(osc_plugin_path(__FILE__) . '_install', 'dliTest\\dliTest_install');\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now you might look at this and go<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">-\u201cBut hey, if dliCore is enabled we don\u2019t register any install hook. So we won\u2019t be able to install our plugin\u2026 and there\u2019s no uninstall hook either\u2026 and\u2026\u201d<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Easy there. As I said, everything is encapsulated. We do have install functions and uninstall functions and all the other stuff to. They are just not globally available.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">dliTestPlugin<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s take a look at our plugin class<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace dliTest;\n\nuse dliLib\\Plugin\\Plugin;\n\nclass dliTestPlugin extends Plugin\n{\n protected function _init() {\n \n }\n\n public function getSupportEmail() {\n return 'osc-support@danielliljeberg.se';\n }\n\n public function installHook() {\n\n }\n\n public function uninstallHook() {\n\n }\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Here you can see that our plugin contains two public function.&nbsp;<strong>installHook<\/strong>&nbsp;and&nbsp;<strong>uninstallHook<\/strong>. These are the functions that will run when the plugin is installed or uninstalled. It actually also automatically handles a lot of other things in the background during installation and installation as well, but we\u2019ll look at that later.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Hooks using dliCore<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>dliCore<\/strong>&nbsp;makes it super easy for you to add a hook to your plugin. Simply create a public function, name it correctly and you have a working hook.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Registering a hook for the&nbsp;<strong>item_detail<\/strong>&nbsp;hook<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function itemDetailHook() {\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Registering a hook for the&nbsp;<strong>before_html<\/strong>&nbsp;hook<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function beforeHtmlHook() {\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see, you use the normal hook name you want to hook against and write that name in camel case instead of using underscores and then you end the name with&nbsp;<strong>Hook<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The exact same behavior&nbsp; is available for&nbsp;<strong>filters<\/strong>, just en the function name in&nbsp;<strong>Filter<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How do we handle that routing thingy to show our file helloWorld file?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Using&nbsp;<strong>dliCore<\/strong>&nbsp;you are free to setup routes like normal in for instance the&nbsp;<strong>_init<\/strong>&nbsp;function of your plugin or even the&nbsp;<strong>index.php<\/strong>&nbsp;file. But that would make me a bit sad.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead you should use&nbsp;<strong>Controllers<\/strong>. Create a subfolder under your plugin and name it&nbsp;<strong>Controllers<\/strong>. Insede we create a file&nbsp;<strong>HelloWorldController.php<\/strong>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?php\nnamespace dliTest\\Controllers;\n\nuse dliLib\\Plugin\\Controller\\BaseController;\n\nclass HelloWorldController extends BaseController\n{\n public function helloWorldAction() {\n\n }\n}\n?><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This controller will handle our logic. That way we can easily keep it separated from the presentation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By adding an&nbsp;<strong>Action<\/strong>&nbsp;function to your controller,&nbsp;<strong>dliCore<\/strong>&nbsp;will automatically create the needed routes for it. For instance the route&nbsp;<strong>dliTest\/HelloWorld\/helloWorld<\/strong>&nbsp;will run our&nbsp;<strong>helloWorldAction<\/strong>&nbsp;function in our&nbsp;<strong>HelloWorldController<\/strong>. All that is done for you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But we passed a&nbsp;<strong>message<\/strong>&nbsp;parameter last time. How do we get the route to understand that it should accept a parameter named&nbsp;<strong>message<\/strong>? Well, you simply add it as a paramater to the action function.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function helloWorldAction($message) {\n\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This will automatically add to the route that a parameter called&nbsp;<strong>message<\/strong>&nbsp;is accepted by the route and will automatically provide your function with the result of that. But how do we make sure the parameter fulfills a specific regexp like we could when we manually crafted our routes? Well, I could have used some array to map function parameters to their regexps etc, but I wanted to keep it all in one place. One place to update if you wanted to add or remove a parameter. At first I was thinking about letting the user provide the regexp in a comment block. But I didn\u2019t really like that. After scratching my head a bit I came to think about the fact that since actions are automatically called I could hijack their&nbsp;<em>default value<\/em>&nbsp;and use that to convey their regular expressions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So in order to make sure it\u2019s only valid to pass the characters&nbsp;<strong>a-Z<\/strong>&nbsp;to the function, we update it like this.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function helloWorldAction($message = '([a-zA-Z]+)') {\n\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This means that adding and removing parameters from actions is extremely fast and easy and you only have to alter code in one place. Instead of having to change your function, update your route etc.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Displaying our message<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You could very well just echo your message in the action.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function helloWorldAction($message = '([a-zA-Z]+)') {\n  echo $message;\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That would print our message in a otherwise empty page. This works alright if the response is some JSON etc. But for presentation of normal pages that\u2019s not how I like to do it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Instead we create a&nbsp;<strong>view<\/strong>&nbsp;file. This is our graphical representation file from a request to our given function. So for&nbsp;<strong>dliTest\/HelloWorld\/helloWorld<\/strong>, which ends up running the&nbsp;<strong>helloWorldAction<\/strong>&nbsp;function of the&nbsp;<strong>HelloWorldController<\/strong>&nbsp;object we create a file named&nbsp;<strong>helloWorld.php<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now we place this file in a sub folder of our plugin&nbsp;<strong>views\\HelloWorld\\helloWorld.php<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<strong>views<\/strong>&nbsp;folder is the top level folder for our views files.&nbsp;<strong>HelloWorld<\/strong>&nbsp;is the name of the controller so that all files owned by a given controller can reside in the same place. The&nbsp;<strong>helloWorld<\/strong>&nbsp;part of our files name is the name of the action function minus the&nbsp;<strong>Action<\/strong>&nbsp;part. That way it\u2019s easy to quickly find a given view file for any action in any controller.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To make it possible to access our&nbsp;<strong>message<\/strong>&nbsp;parameter in the view file we&nbsp;<strong>export<\/strong>&nbsp;it to the&nbsp; view.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function helloWorldAction($message = '([a-zA-Z]+)') {\n  $_this->_exportVariableToView('message', $message);\n}<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Then in our view file we write<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"php\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">echo \\View::newInstance()->_get('message');<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This will echo our message parameter.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In your view file you could now easily add html markup to style your presentation, without having it mixed with all your logic.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Theme specific views<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">It\u2019s also possible for you to create theme specific versions of your&nbsp;views.&nbsp;This allows a developer to add support for specific themes or for users to add alterations to specific themes themselves.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To add a theme specific version of a view file, add a folder under the&nbsp;<strong>views<\/strong>&nbsp;folder and name it according to the themes name and place your views under that. For instance<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>views\/cooltheme\/HelloWorld\/helloWorld.php<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Any file placed in the sub folder of an active theme that matches a given route will be used before the default view is used.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The default views can be copied and used as a starting point.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Extra features<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">dliCore contains a myriad of extra functionality connected to database table management, memory usage, caching, handling objects, managing and sending emails etc. More on this in&nbsp;future posts.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Availability<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">dliCore will be uploaded to the Osclass market so it can be easily installed for any plugin requiring it.<\/p>\n\t\t\t<input type=\"hidden\" id=\"wplinkpress-user-email\" value=\"\" \/>\n<input type=\"hidden\" id=\"wplinkpress-authorize-url\" value=\"https:\/\/www.linkedin.com\/oauth\/v2\/authorization?response_type=code&client_id=77uzug7iq2dnd2&redirect_uri=https%3A%2F%2Fdaniel.liljeberg.io%2Fauthorize-linkedin%2F&state=https%3A%2F%2Fdaniel.liljeberg.io%2Fsv%2Fwp-json%2Fwp%2Fv2%2Fposts%2F32&scope=r_liteprofile%20r_emailaddress%20w_member_social\" \/>\n<input type=\"hidden\" id=\"wplinkpress-post-id\" value=\"32\" \/>\n<div class=\"ui wplinkpress comments\">\n<h3 class=\"ui dividing header\">Comments<\/h3>\n<form id=\"add-wplinkpress-comment\" method=\"POST\"> \n<div class=\"comment add-comment\">\n\t<a class=\"avatar\"><img src=\"https:\/\/daniel.liljeberg.io\/wp-content\/plugins\/wplinkpress\/assets\/media\/non-user-icon.jpg\" \/><\/a>\n\t<div class=\"content\">\n\t<textarea id=\"wplinkpress-comment-text-0\" class=\"wplinkpress-comment-text\" style=\"width:100%;\" placeholder=\"Add a comment...\"><\/textarea>\n\t<div class=\"bottom-layer\">\n\t\t<div class=\"comment-atts\" style=\"float:left;\">\n\t\t\t\t<div class=\"feed-share\">\n\t\t<label class=\"switch tips\">\n\t\t\t<input type=\"checkbox\" id=\"toggle-linkedin-feed\" >\n        \t<span class=\"slider round\"><\/span>\n\t\t<\/label>\n\t\t<span>Share on activity feed<\/span>\n\t\t<\/div>\n\t\t<\/div>\n\t<div class=\"wplinkpress_buttons\">\n\t\t<button id=\"authorize_comment_0\" class=\"authorize_comment\" disabled=\"disabled\">Post with LinkedIn<\/button>\n\t\t<\/div>\n\t<\/div>\n\t<\/div>\n<\/div>\n<\/form>\n<h3 class=\"ui dividing header\"><span class=\"wplinkpress-brand\">Powered by WP LinkPress<\/span><\/h3>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>In our\u00a0previous post\u00a0we looked at the basics of building a plugin for Osclass. There are however quite a few issues that I have observed in almost every plugin I have looked at that I felt I wanted to do differently. Issues I saw with plugins index.php often becomes bloated with functions that handle every aspect&hellip;&nbsp;<a href=\"https:\/\/daniel.liljeberg.io\/sv\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">Streamlining, accelerating and encapsulating Osclass plugin development<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","neve_meta_reading_time":"","footnotes":""},"categories":[3,2],"tags":[],"class_list":["post-32","post","type-post","status-publish","format-standard","hentry","category-dlicore","category-osclass"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Streamlining, accelerating and encapsulating Osclass plugin development - Daniel Liljeberg<\/title>\n<meta name=\"description\" content=\"Using dliCore for Osclass we can create highly encapsulated Object Oriented plugins quickly.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/daniel.liljeberg.io\/sv\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/\" \/>\n<meta property=\"og:locale\" content=\"sv_SE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Streamlining, accelerating and encapsulating Osclass plugin development - Daniel Liljeberg\" \/>\n<meta property=\"og:description\" content=\"Using dliCore for Osclass we can create highly encapsulated Object Oriented plugins quickly.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/daniel.liljeberg.io\/sv\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/\" \/>\n<meta property=\"og:site_name\" content=\"Daniel Liljeberg\" \/>\n<meta property=\"article:published_time\" content=\"2015-04-12T17:59:24+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-04-01T20:02:08+00:00\" \/>\n<meta name=\"author\" content=\"Daniel Liljeberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Skriven av\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Liljeberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Ber\u00e4knad l\u00e4stid\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minuter\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/\"},\"author\":{\"name\":\"Daniel Liljeberg\",\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/#\\\/schema\\\/person\\\/e2c3fe10971c37cff2669f5688834cd7\"},\"headline\":\"Streamlining, accelerating and encapsulating Osclass plugin development\",\"datePublished\":\"2015-04-12T17:59:24+00:00\",\"dateModified\":\"2021-04-01T20:02:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/\"},\"wordCount\":1897,\"publisher\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/#\\\/schema\\\/person\\\/e2c3fe10971c37cff2669f5688834cd7\"},\"articleSection\":[\"dliCore\",\"Osclass\"],\"inLanguage\":\"sv-SE\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/\",\"url\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/\",\"name\":\"Streamlining, accelerating and encapsulating Osclass plugin development - Daniel Liljeberg\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/#website\"},\"datePublished\":\"2015-04-12T17:59:24+00:00\",\"dateModified\":\"2021-04-01T20:02:08+00:00\",\"description\":\"Using dliCore for Osclass we can create highly encapsulated Object Oriented plugins quickly.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/#breadcrumb\"},\"inLanguage\":\"sv-SE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/2015\\\/04\\\/12\\\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/daniel.liljeberg.io\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Streamlining, accelerating and encapsulating Osclass plugin development\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/#website\",\"url\":\"https:\\\/\\\/daniel.liljeberg.io\\\/\",\"name\":\"Daniel Liljeberg\",\"description\":\"The is no place like 127.0.0.1\",\"publisher\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/#\\\/schema\\\/person\\\/e2c3fe10971c37cff2669f5688834cd7\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/daniel.liljeberg.io\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"sv-SE\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/#\\\/schema\\\/person\\\/e2c3fe10971c37cff2669f5688834cd7\",\"name\":\"Daniel Liljeberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"sv-SE\",\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/DanielLiljeberg.png\",\"url\":\"https:\\\/\\\/daniel.liljeberg.io\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/DanielLiljeberg.png\",\"contentUrl\":\"https:\\\/\\\/daniel.liljeberg.io\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/DanielLiljeberg.png\",\"width\":424,\"height\":440,\"caption\":\"Daniel Liljeberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/daniel.liljeberg.io\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/DanielLiljeberg.png\"},\"description\":\"Agile practitioner and advocate. Strong believer in the future of agile organizations, businesses and teams. Got my first computer, a C64, at age 7 and computers has been part of my life since then. Working professionally with development since the early 2000\u2019s in a vast array of technologies and roles. Social, easy going, fun loving guy with an appetite for new challenges and new knowledge who has been \u201cthere\u201d and done \u201cthat\u201d. That\u2019s a good way to sum it all up. Married and father of three kids. All true blessings ;)\",\"sameAs\":[\"https:\\\/\\\/daniel.liljeberg.io\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/danielliljeberg\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Streamlining, accelerating and encapsulating Osclass plugin development - Daniel Liljeberg","description":"Using dliCore for Osclass we can create highly encapsulated Object Oriented plugins quickly.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/daniel.liljeberg.io\/sv\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/","og_locale":"sv_SE","og_type":"article","og_title":"Streamlining, accelerating and encapsulating Osclass plugin development - Daniel Liljeberg","og_description":"Using dliCore for Osclass we can create highly encapsulated Object Oriented plugins quickly.","og_url":"https:\/\/daniel.liljeberg.io\/sv\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/","og_site_name":"Daniel Liljeberg","article_published_time":"2015-04-12T17:59:24+00:00","article_modified_time":"2021-04-01T20:02:08+00:00","author":"Daniel Liljeberg","twitter_card":"summary_large_image","twitter_misc":{"Skriven av":"Daniel Liljeberg","Ber\u00e4knad l\u00e4stid":"11 minuter"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/#article","isPartOf":{"@id":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/"},"author":{"name":"Daniel Liljeberg","@id":"https:\/\/daniel.liljeberg.io\/#\/schema\/person\/e2c3fe10971c37cff2669f5688834cd7"},"headline":"Streamlining, accelerating and encapsulating Osclass plugin development","datePublished":"2015-04-12T17:59:24+00:00","dateModified":"2021-04-01T20:02:08+00:00","mainEntityOfPage":{"@id":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/"},"wordCount":1897,"publisher":{"@id":"https:\/\/daniel.liljeberg.io\/#\/schema\/person\/e2c3fe10971c37cff2669f5688834cd7"},"articleSection":["dliCore","Osclass"],"inLanguage":"sv-SE"},{"@type":"WebPage","@id":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/","url":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/","name":"Streamlining, accelerating and encapsulating Osclass plugin development - Daniel Liljeberg","isPartOf":{"@id":"https:\/\/daniel.liljeberg.io\/#website"},"datePublished":"2015-04-12T17:59:24+00:00","dateModified":"2021-04-01T20:02:08+00:00","description":"Using dliCore for Osclass we can create highly encapsulated Object Oriented plugins quickly.","breadcrumb":{"@id":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/#breadcrumb"},"inLanguage":"sv-SE","potentialAction":[{"@type":"ReadAction","target":["https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/daniel.liljeberg.io\/2015\/04\/12\/streamlining-accelerating-and-encapsulating-osclass-plugin-development\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/daniel.liljeberg.io\/"},{"@type":"ListItem","position":2,"name":"Streamlining, accelerating and encapsulating Osclass plugin development"}]},{"@type":"WebSite","@id":"https:\/\/daniel.liljeberg.io\/#website","url":"https:\/\/daniel.liljeberg.io\/","name":"Daniel Liljeberg","description":"The is no place like 127.0.0.1","publisher":{"@id":"https:\/\/daniel.liljeberg.io\/#\/schema\/person\/e2c3fe10971c37cff2669f5688834cd7"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/daniel.liljeberg.io\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"sv-SE"},{"@type":["Person","Organization"],"@id":"https:\/\/daniel.liljeberg.io\/#\/schema\/person\/e2c3fe10971c37cff2669f5688834cd7","name":"Daniel Liljeberg","image":{"@type":"ImageObject","inLanguage":"sv-SE","@id":"https:\/\/daniel.liljeberg.io\/wp-content\/uploads\/2020\/12\/DanielLiljeberg.png","url":"https:\/\/daniel.liljeberg.io\/wp-content\/uploads\/2020\/12\/DanielLiljeberg.png","contentUrl":"https:\/\/daniel.liljeberg.io\/wp-content\/uploads\/2020\/12\/DanielLiljeberg.png","width":424,"height":440,"caption":"Daniel Liljeberg"},"logo":{"@id":"https:\/\/daniel.liljeberg.io\/wp-content\/uploads\/2020\/12\/DanielLiljeberg.png"},"description":"Agile practitioner and advocate. Strong believer in the future of agile organizations, businesses and teams. Got my first computer, a C64, at age 7 and computers has been part of my life since then. Working professionally with development since the early 2000\u2019s in a vast array of technologies and roles. Social, easy going, fun loving guy with an appetite for new challenges and new knowledge who has been \u201cthere\u201d and done \u201cthat\u201d. That\u2019s a good way to sum it all up. Married and father of three kids. All true blessings ;)","sameAs":["https:\/\/daniel.liljeberg.io","https:\/\/www.linkedin.com\/in\/danielliljeberg\/"]}]}},"_links":{"self":[{"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/posts\/32","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/comments?post=32"}],"version-history":[{"count":6,"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/posts\/32\/revisions"}],"predecessor-version":[{"id":444,"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/posts\/32\/revisions\/444"}],"wp:attachment":[{"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/media?parent=32"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/categories?post=32"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daniel.liljeberg.io\/sv\/wp-json\/wp\/v2\/tags?post=32"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}