Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


NextToNothing last won the day on March 29 2018

NextToNothing had the most liked content!

About NextToNothing

  • Rank
  1. NextToNothing

    2 Clients With the same Client Number

    Why the hell does the column not have a UNIQUE index on the goddamn column you use as an identifier?😱 😱 😱 😱 😱 😱 😱 😱 😱 I mean it should really be the primary key, in an ideal world. If not, at the very minimum, it should be unique indexed. 🤯 If it had the index, the user would have never had their account created in the first place and this whole mess would've been avoided full stop. Not to mention this would clearly break any and all data protection laws.
  2. NextToNothing

    Payment Accounts

    Ok. Then there should probably be an option to disable Payment Accounts? 1) if I don't want clients to use them. But also, 2) when I have no merchant gateways and have explicitly disabled both "Credit Card" and "ACH" in Settings > Company > Accepted Payment Types... the nav item still shows and the page is accessible? Also note that the information given to the client is a bit misleading then. Should probably hide this text if encryption is enabled.
  3. NextToNothing

    Payment Accounts

    Hello, As far as I can tell, payment accounts are practically useless when encryption is enabled in Blesta? A client can't select any existing accounts when paying an invoice or ordering a new service. However, they can still add, edit, and manage existing accounts - as well as save their new payment method - which seems kind of pointless if they cant ever use them? The exact code used for rendering payment accounts in the pay selection screen: if (!empty($payment_accounts) && !$this->Html->ifSet($require_passphrase)) {
  4. NextToNothing


    I agree the current way of templating does the job. However, it is a bit cumbersome, and in some cases can be limiting with the the whole "pages expected to be rendered within the structure.pdt file" - opposed to actual inheritance. When I started coding the template files, it thrown be back a good few years back to the days of procedural PHP code. Twig is more OO in it's design. It makes heavy use of inheritance and trait-like blocks/includes. It just makes more sense to utilise such features. I mean, you could write an entire application in procedural PHP code today, and it'll do the job, yeah - but there are reasons we choose to code in OO with classes etc. Personally, I think a good metaphor is that; templating (like Twig) is the same to PHP, that a "preprocessor" (like Sass/Less) is to CSS. You can make your code adhere more to DRY principles, by utilising thing like mix-ins and inheritance. Not to mention all the other useful features such as auto-escaping, etc.
  5. NextToNothing


    Proof of concept: From what I can find, the template rendering is handled inside minPHP (the framework Blesta uses). With a couple of changes, you can get Twig working along side the existing rendering. Obviously, to optimally utilise twig, you'd have to implement proper caching, fine tune options for Blesta, etc. This poc allows for use of .pdt files along side .html.twig files, in order to make any transitions between the two a lot easier. (@BlestaStore) Add Twig as a composer dependency. Note: This is easier said than done if you're not an employee of Phillips Data, Inc. due to autoloading. The easiest way I found was to create a new directory and composer require the files there, then edit lib/init.php to load your autoloader as well. Edit the following in vendors/minphp/bridge/src/Lib/View.php: <?php use Minphp\Bridge\Initializer; /** * Allows the creation of views. */ class View extends Language { // ... /** * Returns the output of the view * * @param string $file The file used as our view * @param string $view The view directory to use * @return string HTML generated by the view */ final public function fetch($file = null, $view = null) { $this->setView($file, $view); $base = $this->container->get('minphp.constants')['ROOTWEBDIR'] . $this->view_path . 'views' . DIRECTORY_SEPARATOR . $this->view . DIRECTORY_SEPARATOR; $fileTwig = $this->file . '.html.twig'; $fileLegacy = $this->file . $this->view_ext; if (file_exists($base . $fileTwig)) { return $this->fetchTwig($base, $fileTwig); } return $this->fetchLegacy($base . $fileLegacy); } private function fetchTwig($base, $file) { $twig = new Twig_Environment( new Twig_Loader_Filesystem( $base, $base ), array( 'autoescape' => false, ) ); return $twig->render( $file, array_merge( [ 'this' => $this, ], $this->vars ) ); } private final function fetchLegacy($file) { if (is_array($this->vars)) { extract($this->vars); } if (!file_exists($file)) { throw new Exception(sprintf('Files does not exist: %s', $file)); } ob_start(); // Start output buffering include $file; // Include the file $contents = ob_get_clean(); // Get the contents of the buffer and close buffer. return $contents; // Return the contents } // ... } Done - Twig files will now be rendered Twig will be preferred. So, if you have client_main.pdt and client_main.html.twig, the twig version will be rendered. If no twig version is available, it will load the pdt version Moving forward from the proof-of-concept, you will be able to recode all the template files to use Twig. Preferably, coding them in Twig will allow the use of {% extends %}, and then the whole code for rendering in Blesta becomes a lot simpler (no need for $structure_view in Controller.php!) Looking forward to comments Edit: Try out Twig, with this new client_main.html.twig file: {{ myinfo }} <div class="col-md-9 right_content"> {{ message }} <script> $(document).ready(function() { $(".right_content").blestaLoadWidgets({ fetch_uri: "{{ this.base_uri|e }}main/getwidgets/ {{ client.id|e }}" }); }); </script> </div>
  6. NextToNothing


    Hey All, Coming from a background in developing with Symfony, I've used Twig a lot. Also used templating engines such as smarty and mustache/handlebars - but I believe Twig to be the better of the bunch. I've seen there was a little discussion about Twig in late 2016 and mid 2017. However, I thought it might be a nice idea to have a constructive discussion about Twig and Blesta? Even if the end decision was not to use Twig, the discussion might help improve the templating system. Most notably for new-comers to Blesta from competitors or a background like mine (Symfony/Twig or Laravel/Blade). I'll start off with a few points: Conciseness Personally, I believe Twig to be more easy to read and follow the logic, given it's brevity. Also, since it uses braces ({}) and not angled brackets (<>), it helps give a contrast between template code and the actual HTML. All this helps readability, which can speed up development and maintainability. Arguably, the same could be achieved in PHP via short tags like <? ?> and <?=$var?> - but I believe you may need to enable them in PHP, which is probably why Blesta isn't using them already (given the self-hosted nature). <div class="row<?php echo (!$this->Html->ifSet($show_header, true) ? ' login' : '');?>"> <?php if (!empty($active_nav['secondary'])) { ?> <div class="col-md-3"> <div class="list-group"> <?php foreach ($active_nav['secondary'] as $link => $value) { ?> <a href="<?php $this->Html->_($link);?>" class="list-group-item borderless left-nav <?php echo ($value['active'] ? 'active' : '');?>"> <i class="<?php $this->Html->_($value['icon']);?>"></i> <?php $this->Html->_($value['name']); ?> </a> <?php } ?> </div> </div> <div class="col-md-9"> <div class="row"> <?php echo $content;?> </div> </div> <?php } else { echo $content; } ?> </div> versus... <div class="row{% if not show_header %} login{% endif %}"> {% if active_nav.secondary is not empty %} <div class="col-md-3"> <div class="list-group"> {% for link, value in active_nav.secondary %} <a href="{{ link|e }}" class="list-group-item borderless left-nav {% if value.active %}active{% endif %}"> <i class="{{ value.icon|e }}"></i> {{ value.name|e }} </a> {% endif %} </div> </div> <div class="col-md-9"> <div class="row"> {{ content }} </div> </div> {% else %} {{ content }} {% endif %} </div> (I didn't test this Twig code, just to confirm) Control Structure Syntax This kind of comes into conciseness, but is only really for PHP. It might be beneficial to use the alternative syntaxes, instead of braces {} in the pdt templates. It would certainly help me get less confused when reading large chunks http://php.net/manual/en/control-structures.alternative-syntax.php IDEs I use PHPStorm, and it has features for Twig, such as better highlighting, auto-completes, etc. With pdt templates being literally PHP, I had to just set them to plain-ol' PHP files - meaning no helpers from the IDE that can speed up development. Inheritance, blocks I think this is probably quite a big point, as blocks are more-or-less how the templating engine in Blesta works - except it's all in the core code. Again, it helps readability - given that from just the template file, I know all of the templates that are gonna be executed. As an example, it can also be useful if someone wanted to change other code on specific pages. In Twig, I'd be able to edit just the one template file - however, with the current system, I'd have to edit core files, which would end up being a pain with upgrades overwriting the files. {% extends "structure.html" %} {% block content %} <b>Content of the page...</b> {% endblock %} opposed to just having a file on it's own with the page content, and having to rely on the core code to define everything else: <b>Content of the page...</b> Extensibility Obviously, PHP is PHP, and you can do what you like with creating functions etc (however, loading them into the template engine is probably another dicussion). Twig is very versatile in the respect. For example, phpBB made the switch from their own engine to Twig, and was able to code extensions to Twig to allow all their old templates to run under Twig. https://www.phpbb.com/community/viewtopic.php?f=461&t=2424606 Everything else over on the Twig homepage -https://twig.symfony.com/ Obviously, it'll involve a bit of work to move over to Twig, but I feel it would be beneficial in the long run, help new-comers, and more importantly help grow the development of themes for Blesta. Given Blesta has a template engine orchestrating everything, I might have a little play around with integrating it myself. 🤔 Hopefully we get a good discussion going on the topic? sidenote - I noticed that templates for plugins can't get overwritten in the app/views/ directory? Thought this was a bit odd, given that most template files have a unique name. So, could we possibly check the app/views/ first before going back to the plugin default. Personally, I wanted to edit a template file in the support_manager plugin but keep all my theme files in one central location (with Git). Unfortunately, I think that I might have to end up with template files here there and everywhere? :S
  7. NextToNothing

    validateService $vars "configoptions" keys inconsistent

    Hey Tyson, Not entirely sure on the difference between a module and a service module. It's the method inside a module class - e.g. located at /components/modules/Supercoolmodule/Supercoolmodule.php From the docs: https://docs.blesta.com/display/dev/Module+Methods#ModuleMethods-validateService($package,array$vars=null) In the example for addService(), it's suggested to call validateService(). However, the addService() method is passed different $vars['configoptions'] keys to when the validateService() method is called internally by Blesta. The var_dump() outputs I posted are shown when blesta is adding the service/calls addService(). Hopefully that makes a bit of sense?
  8. Hey there, Looks like a little bug. In validateService(), when dumping $vars['configoptions'], the keys for each options can change from an ID to the given name - depending on when the function is being called. Putting a var_dump() at the top of the function yields this, when loading the service creation/order complete page. array(2) { [1]=> string(1) "1" [2]=> string(4) "true" } array(2) { [1]=> string(1) "1" [2]=> string(4) "true" } array(2) { ["coolOption"]=> string(1) "1" ["anotherAwesomeOption"]=> string(4) "true" } array(2) { ["coolOption"]=> string(1) "1" ["anotherAwesomeOption"]=> string(4) "true" } array(2) { ["coolOption"]=> string(1) "1" ["anotherAwesomeOption"]=> string(4) "true" }