Invalid Form Token Please Reload This Form and Submit Again Https Concrete5
Monitor invalid SSL certificates
- 27.04.2020
- Uncategorized
It shouldn't happen, but every bit oft, it can yet happen. Sometimes SSL certificates aren't created properly. The effect of it can exist a nasty error message like this:
certificate routines:X509_check_private_key:key values mismatch
In my case information technology was reported by nginx with this:
Apr 27 05:30:51 localhost nginx-rc[3120]: nginx: [emerg] SSL_CTX_use_PrivateKey("/etc/nginx-rc/conf.d/my-server.d/server.primal") failed (SSL: mistake:0B080074:x509 certificate routines:X509_check_private_key:fundamental values mismatch)
As you lot tin can see, it is reported every bit "emerg" which means nginx won't be happy virtually this. In my case this problem caused other vhosts to fail as nginx couldn't reload the configuration and thus couldn't reload the new letsencrypt certificates.
Since I was a flake in a rush I simply rebooted the server, just that made it even worse. nginx didn't start at all and I had to wait at the log files a bit closer. Recreating the certificate that wasn't created correctly was all it took, but knowing that you take to do that, is what's catchy.
Go telegram message if a certificate is invalid
If you haven't sent a message to telegram from your command line, check this article: https://www.marcodena.it/blog/telegram-logging-handler-for-python-java-bash/
In short:
- You lot befriend the botfather
- You result a control /newbot, enter a name and yous'll get token
- You commencement a conversation with your bot and employ that chat id in your script
We can use openssl to go the modulus of the fundamental as well as the certificate. They both take to friction match, otherwise the document is all information technology takes. My script is used with runcloud, just just adjust the path in the loop to get it working in your environment:
#!/bin/fustigate TELEGRAM_TOKEN=<token from telegram> TELEGRAM_CHAT_ID=<chat id from telegram> URL="https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" shopt -s globstar for keyFile in /etc/nginx-rc/conf.d/*/server.key; do crtFile="${keyFile::-three}crt" keyFileModulus=$(openssl x509 -noout -modulus -in $crtFile) crtFileModulus=$(openssl rsa -noout -modulus -in $keyFile) if [ "$crtFileModulus" != "$keyFileModulus" ]; then gyre -s -X POST $URL -d chat_id=$TELEGRAM_CHAT_ID -d text="SSL document is invalid, recreate $keyFile" > /dev/nothing fi washed
Working with queues in concrete5
- 19.02.2017
- Concrete5
A queue can be rather useful when y'all want to process a lot of information, simply also when I just want to make sure things react quickly. Let'southward have a look at a simple instance where you lot might want to send an e-mail.
In a lot of cases people send east-mails right in a controller action. This is okay for a lot of sites, simply sometimes if things are mission critical it helps to use a queue. Imagine what happens if there'southward a temporary problem with the mail system, since you're sending it right in your controller you'll probably prove the user an fault bulletin telling him that something went wrong. Seeing errors is hardly ever a adept thing, with a queue yous could use a simple performance to put the activeness in a queue and procedure it later. If it fails you could try over again a bit later and if information technology fails permanently put information technology in a log file you're monitoring.
There might too exist a maintenance task that y'all tin can finish earlier PHP times out. Using a queue would make information technology more than solid, put every object you want to process in a queue and process it piece past piece.
Putting things in the queue
It's fairly elementary to put things the queue. All you need is a queue name to ensure yous can keep your tasks apart and the information you need subsequently to process the item from the queue:
employ Physical\Core\Foundation\Queue\Queue; $queue = Queue:: get ( 'queue-demo' ) ; $queue -> send ( i ) ;
utilise Concrete\Core\Foundation\Queue\Queue; $queue = Queue::go('queue-demo'); $queue->ship(1);
With this we are putting the number 1 in a queue called "queue-demo". Now that nosotros take objects in our queue we need to process them.
Processing queue
When processing a queue we apparently have to use the same queue proper noun.
use Concrete\Cadre\Foundation\Queue\Queue; $queue = Queue:: get ( 'queue-demo' ) ; $queueMessages = $queue -> receive ( 10 ) ; foreach ( $queueMessages as $msg ) { $userId = $msg -> body ; // load the object for the user ID and process it $queue -> deleteMessage ( $msg ) ; }
use Concrete\Core\Foundation\Queue\Queue; $queue = Queue::get('queue-demo'); $queueMessages = $queue->receive(10); foreach ($queueMessages equally $msg) { $userId = $msg->torso; // load the object for the user ID and procedure it $queue->deleteMessage($msg); }
That's basically all you need to do, but y'all'll of course demand to put that lawmaking somewhere.
concrete5 has an like shooting fish in a barrel to extend CLI API. You derive a class from "Symfony\Component\Console\Command\Command", implement the "execute" method and handle your queue there. Once you register your command, you tin can access it by running "./concrete/bin/concrete5"
Y'all can find a complete example here: https://github.com/Remo/concrete5-queue-demo. Here are some of the relevant lines:
- Annals CLI control in controller
- Configure command, the proper name is what y'all'll specify when running the command
- Locking and unlocking process. Helps to ensure the command is only running in one case.
- Getting items from queue and looping through them
You'll just have to run your command regularly to execute it, a cronjob like this should do the fox: "./concrete/bin/concrete5 queue-demo:process-notifications".
There's also a way to handle everything in a task which is peculiarly useful for maintenance tasks as information technology doesn't require that yous add queue items initiaited by a user action. There's a skilful article in the official documentation most this: https://documentation.concrete5.org/developers/jobs/creating-and-scheduling-a-queueable-job.
Benefits
- Not-blocking executing of tasks
- Avoid timeouts when treatment a lot of data
Disadvantages
- Adds a flake more complication to your code
- concrete5 queues require polling on the executing side, calculation a delay to your task. Deosn't apply to queues in full general, if you employ something like beanstalk y'all can procedure tasks immediately
Some of the code was written by Michele Locati. Hope yous enjoy working with queues!
Group Markers in Google Map with Gmaps Marking Clusterer
- 07.12.2016
- JavaScript
If y'all take a map with a lot of markers you'll eventually accept a hard fourth dimension to see all the maps, specially if you zoom out. At that place's a google library called "Js Marker Clusterer" which helps out, information technology simply builds clusters of markers close together. Unfortunately information technology'south not maintained anymore, simply there aren't many good alternatives. That's why we've decided to join our effort and create a fork under a new system. Nosotros couldn't use the same name but wanted to stay close to it's original name. Because of that we've decided to go with Gmaps Marker Clusterer. Information technology'south an attempt to avoid having too many forks which eventually die because of missing interest. Right now nosotros are two contributors, simply we are obviously interested in getting more assist. Yous tin can discover the github page here https://github.com/gmaps-marker-clusterer/gmaps-marker-clusterer and the documentation (work in progress) here: https://gmaps-marker-clusterer.github.io/gmaps-marker-clusterer/
Here'southward a simple example showing y'all how to create a google map with clusters. Information technology assumes you have a global array called "information", information technology can be found here https://gmaps-marker-clusterer.github.io/gmaps-marking-clusterer/assets/js/data.json:
var markers = [ ] ; for ( var i = 0 ; i < 100 ; i++ ) { var dataPhoto = data.photos [i] ; var latLng = new google.maps.LatLng (dataPhoto.latitude , dataPhoto.longitude ) ; var marker = new google.maps.Marker ( { position: latLng } ) ; markers.push button (marker) ; } var options = { imagePath: 'https://raw.githubusercontent.com/gmaps-marker-clusterer/gmaps-marker-clusterer/master/images/chiliad' } ; var markerCluster = new MarkerClusterer(map, markers, options) ;
var markers = []; for (var i = 0; i < 100; i++) { var dataPhoto = data.photos[i]; var latLng = new google.maps.LatLng(dataPhoto.latitude, dataPhoto.longitude); var marker = new google.maps.Marker({ position: latLng }); markers.push(mark); } var options = { imagePath: 'https://raw.githubusercontent.com/gmaps-mark-clusterer/gmaps-marker-clusterer/primary/images/1000' }; var markerCluster = new MarkerClusterer(map, markers, options);
As you can see nosotros basically just create our markers through MarkerClusterer and this will then add all of them in a nice mode to the already existing map object. A complete example with google maps (you might have to set your own fundamental subsequently &key=) would and then look like this:
<style type="text/css"> #map { width: 600px; height: 400px; max-width: 100%; } </style> <div id="map-container"><div id="map"></div></div> <script> office initialize() { var center = new google.maps.LatLng(51.5074, 0.1278); var map = new google.maps.Map(document.getElementById('map'), { zoom: iii, center: center, mapTypeId: google.maps.MapTypeId.ROADMAP }); var markers = []; for (var i = 0; i < 100; i++) { var dataPhoto = data.photos[i]; var latLng = new google.maps.LatLng(dataPhoto.latitude, dataPhoto.longitude); var marking = new google.maps.Marker({ position: latLng }); markers.push(marker); } var options = { imagePath: 'https://gmaps-mark-clusterer.github.io/gmaps-marking-clusterer/assets/images/grand' }; var markerCluster = new MarkerClusterer(map, markers, options); } </script> <script src="markerclusterer.js"></script> <script src="information.json"></script> <script async defer src="https://maps.googleapis.com/maps/api/js?callback=initialize&key="></script>
<way type="text/css"> #map { width: 600px; summit: 400px; max-width: 100%; } </manner> <div id="map-container"><div id="map"></div></div> <script> part initialize() { var center = new google.maps.LatLng(51.5074, 0.1278); var map = new google.maps.Map(certificate.getElementById('map'), { zoom: 3, center: eye, mapTypeId: google.maps.MapTypeId.ROADMAP }); var markers = []; for (var i = 0; i < 100; i++) { var dataPhoto = data.photos[i]; var latLng = new google.maps.LatLng(dataPhoto.latitude, dataPhoto.longitude); var marker = new google.maps.Marker({ position: latLng }); markers.push(mark); } var options = { imagePath: 'https://gmaps-marker-clusterer.github.io/gmaps-marker-clusterer/assets/images/m' }; var markerCluster = new MarkerClusterer(map, markers, options); } </script> <script src="markerclusterer.js"></script> <script src="data.json"></script> <script async defer src="https://maps.googleapis.com/maps/api/js?callback=initialize&key="></script>
Y'all can observe a working example here https://gmaps-marker-clusterer.github.io/gmaps-marker-clusterer/instance-simple/. A real life case can exist found hither, a Swiss site showing you interesting places to spend your fourth dimension in the nature with your kids, playgrounds, fireplaces and more than: https://www.freizeitplatz.ch/
VueJS2 UI exam – Quasar Framework
- 25.x.2016
- JavaScript, Vue.JS
Later I published my article most VueStrap things take changed a bit. We at present have the awesome version 2 of VueJS and patently we demand to build a UI with it at some point. I took that as a reason to have some other look at the UI libraries.
I was able to find a few frameworks for VueJS2. I managed to observe three and had a quick await at all of them
- http://vuikit.github.io/vuikit/ Experience clean and simple. Button checkboxes where only the button border changes feels a fleck too subtle to me, just overall information technology looks pretty good.
- http://quasar-framework.org/ Seems to take a focus on mobile devices, just works on a desktop too. Extensive documentation, dandy starting time impression.
- http://element.eleme.io/ Unfortunately this is only in Chinese, but some parts are in two languages, that's adept plenty to notice the component you need. Looks pretty solid too, but seems to have less components than Quasar.
I've decided to give Quasar a become equally information technology feels very complete and solid.
Getting started with Quasar Framework.
In that location'due south not much to explain, the documentation is up to date and easy to understand. If you need more details, apply the author's documentation: http://quasar-framework.org/guide/index.html
Here's what I did:
npm install -g quasar-cli quasar init quasar-test cd quasar-examination npm install
npm install -m quasar-cli quasar init quasar-exam cd quasar-examination npm install
No problem in that location, everything installed fine. Information technology seems similar in that location are two different themes. The default material theme:
A second i called iOS
Allow's run across how it looks:
Crawly, textile and iOS style in a second!
Adding a new Quasar framework component
The commencement screen is made of the index.vue establish in src/components. Let'south try to add a fixed button like shown here: http://quasar-framework.org/components/floating-action-buttons.html
When I tried to remove the logo I received an error:
How awesome is this, information technology helps me to write nicely formatted code and fifty-fifty tells me right in the browser with live reload. Let's remove the trailing spaces and requite it some other try. Spaces removed and it works, no issues at all!
I similar tree, the dark-green ones, but besides the ones on my screen. Let'due south have a wait at the documentation: http://quasar-framework.org/components/tree.html
Copy the model information to our alphabetize.vue and add the element to the template. Again, everything works smoothly:
I'm impressed with Quasar Framework! The outset impression lasts! I played effectually with a few more things and whatever I practise work well. There'south fifty-fifty a live reload plugin for Android. All those features at this quality is amazing.
Vue.JS UI Exam / VueStrap
I recently became quite fond of Vue.JS. It feels like a simpler version of AngularJS i / Angular 2 and so far came with everything I was looking for. It took me a while to get everything up and running, npm with all its dependencies, multiple versions and more alpha than beta libraries it tin exist a bit annoying, but once things are running smoothen, it's quite job. Naturally I need to have some kind of graphical interface.
In that location's a smashing listing of Vue.JS libraries, ever a good start if you need something: https://github.com/vuejs/crawly-vue
As I'm pretty experiences with bootstrap, I just felt that I should get with something not completely new to me. With currently 2364 stars and a lot of activity merely a few hours ago the projection seems to be very much alive. I was too happy to run into 45 different contributors, the bulk of the piece of work done by fewer people though. Here'south the project's home: https://github.com/yuche/vue-strap.
Getting started
First nosotros accept to create a Vue.JS project. Bold yous've got node and npm installed, yous tin install the vue-cli tools to do that:
In one case you've got that installed, y'all tin can create a simple project past running this control:
vue init webpack-elementary#one.0 vue-strap-test
vue init webpack-simple#ane.0 vue-strap-test
Delight note that I've specify version 1 as version 2 isn't stable yet. Once the project has been created we have to install the npm modules.
cd vue-strap-test npm install
cd vue-strap-exam npm install
At present that nosotros've got our empty Vue.JS project nosotros have to add VueStrap. Nosotros can easily exercise that by running this command
npm install vue-strap bootstrap fashion-loader
npm install vue-strap bootstrap style-loader
Please note that I'g also installed bootstrap as nosotros require its CSS and style-loader and then that we tin hands embed bootstrap from our component. More about that later.
Everything is installed, let's open src/App.vue and add our components. First we add together something to the template section, right after the h1 element:
<alert type="success"> Success! </warning>
<alert type="success"> Success! </alert>
In the script section we also take to import two files, our VueStrap component and of grade bootstrap:
import { warning } from 'vue-strap' import 'bootstrap/dist/css/bootstrap.css'
import { alert } from 'vue-strap' import 'bootstrap/dist/css/bootstrap.css'
And and then nosotros as well demand to brand the imported component available by adding these lines:
The consummate component looks similar the file shown hither https://github.com/ortic/vue.js-ui-test/blob/master/vue-strap-test/src/App.vue
If y'all then go back to your terminal, yous can simply blazon npm run dev
so open your browser at http://localhost:8080
The squeamish thing about running dev is that it automatically reload if y'all alter your code. Hither are two more changes to the component to add together more bootstrap features:
- https://github.com/ortic/vue.js-ui-examination/commit/46d553b084eac20fff12788f4369973fd01318bf
- https://github.com/ortic/vue.js-ui-examination/commit/609ee8bee2e7e93683364459163b6e9f1a4e28c5
If everything worked, y'all should some something similar this:
Determination about VueStrap
Existence Bootstrap makes information technology rather powerful and very familiar to lots of developers, that's certainly a big plus. I somehow like that they implemented the whole JavaScript office using Vue.JS, that makes it lighter and more Vue.JS similar, but reinventing this part might crusade some new bugs to evidence up also. It seems like at that place are still a few bugs which I can find in very piddling time. My first attempt with browserify on tiptop of an existing projection lead me to this trouble. https://github.com/yuche/vue-strap/issues/198. In this attempt, the popover component didn't seem to work. The DOM gets inverse, merely the CSS holding display is nevertheless prepare to none, here's the commit https://github.com/ortic/vue.js-ui-test/commit/a3fab52f9195d90995ada87d3e031a30575888ea.
While it seems to be pretty cool, I'm not convinced it's stable plenty to be used in a big calibration project unless yous're okay with fixing a few things yourself. It'southward costless afterwards all and the code isn't too difficult to sympathize once yous've got a hang of Vue.JS. I'll keep on testing other frameworks to narrow things a bit down.
concrete5.seven – Custom Toolbar Button
- 21.12.2015
- Concrete5
concrete5 had an API to add together a custom button to the inline editing toolbar. Here'south the commodity for the older five.half-dozen version: http://www.codeblog.ch/2012/04/concrete5-custom-toolbar-button/
In 5.7 a few things take inverse. The thought is notwithstanding the same, but you'll have to apply namespaces and loading classes is a bit different too.
Here's how to get access to the menu helper:
1 | $menuHelper = Core:: make ( 'helper/physical/ui/bill of fare' ) ; |
$menuHelper = Core::make('helper/concrete/ui/bill of fare');
You lot then have to call the addPageHeaderMenuItem method. Assuming you've already got a bundle, this is how the on_start method could wait like:
ane 2 3 4 five six seven 8 nine 10 11 12 xiii 14 15 sixteen 17 18 | public function on_start( ) { $req = \Asking:: getInstance ( ) ; // Make sure we don't inject our lawmaking if it'due south chosen by an AJAX request if ( ! $req -> isXmlHttpRequest ( ) ) { /* @var $menuHelper \Physical\Core\Application\Service\UserInterface\Menu */ $menuHelper = Core:: brand ( 'helper/concrete/ui/menu' ) ; $menuHelper -> addPageHeaderMenuItem ( 'ortic_btn' , $this -> pkgHandle , array ( 'icon' => 'question' , 'label' => t( 'Ortic' ) , 'position' => 'correct' , 'href' => 'http://world wide web.ortic.com' , 'linkAttributes' => array ( 'id' => 'ortic-push' , 'target' => '_blank' ) ) ) ; } } |
public function on_start() { $req = \Request::getInstance(); // Make certain we don't inject our lawmaking if information technology's called by an AJAX request if (!$req->isXmlHttpRequest()) { /* @var $menuHelper \Concrete\Core\Application\Service\UserInterface\Menu */ $menuHelper = Core::make('helper/concrete/ui/menu'); $menuHelper->addPageHeaderMenuItem('ortic_btn', $this->pkgHandle, array( 'icon' => 'question', 'label' => t('Ortic'), 'position' => 'right', 'href' => 'http://www.ortic.com', 'linkAttributes' => assortment('id' => 'ortic-button', 'target' => '_blank') )); } }
Delight note that nosotros're checking if the request is handled by an AJAX asking. This can help to avert collisions if y'all inject more things.
After that you'll simply have to create one more file in your package. Within "menu_items", create a new folder with the button name, in my case "ortic_btn" (the first argument of addPageHeaderMenuItem ) and add a content like this:
1 2 iii 4 5 half-dozen 7 eight ix x eleven 12 13 xiv | <?php namespace Physical\Package\OrticToolbar\MenuItem\OrticBtn; class Controller extends \Concrete\Cadre\Awarding\UserInterface\Carte du jour\Item\Controller { /** * Return false if you don't want to display the button * @render bool */ public function displayItem( ) { render true ; } } |
<?php namespace Concrete\Parcel\OrticToolbar\MenuItem\OrticBtn; class Controller extends \Concrete\Core\Application\UserInterface\Carte\Item\Controller { /** * Return false if you don't desire to display the button * @return bool */ public function displayItem() { return true; } }
Please note that "OrticToolbar" refers to my package.
You lot tin can observe the complete case on github: https://github.com/ortic/ortic-button
concrete5.7 Open Source Packages
- 15.06.2015
- Concrete5
concrete5 version 5.seven is out for a couple of calendar month and as always with a major version, old stuff might is cleaved and it takes a while to find new packages, resources and information. I tried to assemble a listing of open up source packages for 5.7 which you can use in your project or learn from to build your own packages. Please note that some packages aren't stable yet, it'due south not a listing for terminate-users but rather a listing for concrete5 developers eager to learn about building add-ons.
Please let me know if I accept missed a package, I'll happily update my list.
Bundle | URL | Clarification | |
---|---|---|---|
Add Multiple Pages | https://github.com/Mesuva/add_multiple_pages | Dashboard extension to add multiple pages in i go | |
Redactor anchors plugin | https://github.com/csebe/anchors_redactor_plugin | Redactor plugin to create anchors inside the edited text | |
Attribute Forms | https://github.com/Remo/concrete5-attribute-forms | Create forms usings attributes to get more than flexibility, work in progress | |
Sound Histrion | https://github.com/cpill0789/HTML5-Audio-Histrion-Basic | Audio player | |
C5 Downloader | https://github.com/tao-s/c5downloader | Script to download and install concrete5 | |
Cal Packet | https://github.com/olsgreen/cal_package | Agenda functionality | |
CKEditor | https://github.com/Mesuva/ckeditor_content | Inline editor using CKEditor, doesn't integrate file manager | |
CSV XML Converter | https://github.com/hissy/addon_csv_xml_converter | Create an XML file based on a CSV input y'all can import to your concrete5 site | |
Designer Content 5.7 | https://github.com/concrete5japan/c5_designer_content_57 | Create blocks for concrete5 using a visual interface | |
Programmer Tools | https://github.com/ExchangeCore/concrete5-Developer-Tools | Developer Tools | |
Epicblue | https://github.com/caomicc/Epicblue | concrete5 theme | |
Fotorama Gallery | https://github.com/olsgreen/fotorama_package | Adds a block using the Fotorama gallery script | |
Foundation Sites | https://github.com/core77/foundation_sites | Package containing a theme and various block templates using foundation | |
Handsontable | https://github.com/Mesuva/msv_table | Inline block using Handsontable to create tables using an excel similar interface | |
LDAP Login | https://github.com/go2sh/concrete5-ldap-login | Package extending the hallmark organization | |
Lits files | https://github.com/Mesuva/list_files_from_set | Lists files from a file set | |
Mai Chimp | https://github.com/core77/mail_chimp | Block that let's you signup to mailchimp newsletter lists | |
Transmission NAV | https://github.com/concrete5japan/Transmission-Nav | Build a navigation by manually assembling your pages | |
Multilingual Global Surface area | https://github.com/hissy/addon_multilingual_global_area | Makes global area global per language | |
Open up Graph Tags | https://github.com/hissy/c5-open-graph-tags-lite | Add open graph tags to your site | |
Package Installer | https://github.com/Remo/concrete5-bundle-installer | Allows you to upload a Null file containing a package to exist instaled | |
Farsi Payment for VividStore | https://github.com/Shayan66/parsian_payment_vividstore | Persian Payment for VividStore | |
Plainly Text Attribute | https://github.com/Remo/concrete5-attribute-apparently-text | Attribute to add static text, useful in combination with attribute forms | |
QR Code | https://github.com/Remo/concrete5-qr-code | Block to embed QR code in your website | |
Razor Commere | https://github.com/RazorCommerce/razor-commerce/ | An east-commerce solution | |
Sakan | https://github.com/concrete5japan/sakan | theme based on bootstrap 3 | |
Snowfall Migrate | https://github.com/mkly/Snow-Migrate | concrete5 theme | |
Social Share | https://github.com/hissy/c5_social_share_lite | Adds share icons to your site | |
End Forum SPAM | https://github.com/ExchangeCore/Concrete5-Stop-Forum-Spam | SPAM protection add-on | |
SVG Prototype | https://github.com/Mesuva/svg_image | SVG image with a bitmap fallback | |
Tweet Feed | https://github.com/olsgreen/tweet_feed_package | Adds a twitter feed to your site | |
Under Construction | https://github.com/mkly/Under-Construction | Adds an under construction page | |
Vanity URLs | https://github.com/mkly/Vanity-Urls | Allow'southward yous admission user profile pages using /@username | |
Vivid Shop | https://github.com/VividWeb/vivid_store | An east-commerce solution |
concrete5.7 upgrade packages
Every bit you might have heard, a major release of concrete5 has been published. If you haven't, here'south a listing of things that have changed http://world wide web.concrete5.org/documentation/background/version_history/5-seven-0/.
In this post, I'm going to look at the process of upgrading an existing package which worked for version 5.six. I'1000 doing this step by pace to evidence to prove you lot possible fault messages which might assist you lot catechumen y'all ain packages, merely delight note that I'one thousand aiming at concrete5 developers knowing version five.6 and will thus skip a few things which haven't changed.
I'thou going to use a unproblematic package I wrote a while ago, it'due south the zoom image block which allows you lot to zoom into a single image. Much similar lightbox, simply limited to a single motion picture. The code tin be institute here https://github.com/Remo/concrete5-zoom-image.
The Directory Construction of concrete5.7
Once you lot've downloaded and installed concrete5.7 you lot'll probably see that the directory construction has inverse quite a bit:
- The root directory
- There are only four directories left
- application – this is where your overrides for your own site should exist placed
- physical – this is still the core and should never be touched unless
- packages – this is patently the place where you have to add your own packages
- updates – still the aforementioned, here's where you tin can find an updated cadre
- What new directories are there
- hallmark – at that place'southward a pretty neat authentication organization y'all can extend, by default at that place's a born concrete5 organisation and 1 supporting facebook
- bootstrap – as the name tells you, hither's where things get started, loaded etc.
- src – this is where y'all can find the PSR4 auto-loaded classes, accept a look at this directory to get acquainted with the new things in concrete5
- vendor – version v.7 partially uses composer.json to manage dependencies, this is where yous can find the libraries installed past composer
Installing the zoom epitome bundle
Before you install anything, make certain you've got a database dump y'all tin easily restore, it might make things easier.
I just downloaded the latest version from github and placed it in a directory called zoom_image
in the packages
directory. In concrete5, type add functionality
in the search box and select the first particular. You'll already see your get-go exception at this signal:
.
We can't see any details about the mistake, now what? You tin either expect at your database and check the content of the Logs
table or become dorsum and type debug
in the search box. Navigate to debug settings and check Bear witness errors in page.
. If you so to back to install your package, you'll see a nice output produces by https://github.com/filp/whoops. It tells use, that we can't redeclare the course ZoomImagePackage. That'due south because concrete5.vii uses namespaces for pretty much everything. To get around this problem, we have to update the controller in our package. The first few lines take to expect like this:
1 2 three 4 5 6 vii 8 ix 10 eleven | <?php namespace Concrete\Parcel\ZoomImage; defined ( 'C5_EXECUTE' ) or die ( 'Access Denied.' ) ; grade Controller extends \Concrete\Core\Package\Package { protected $pkgHandle = 'zoom_image' ; protected $appVersionRequired = '5.seven.0' ; protected $pkgVersion = 'two.0.0' ; |
<?php namespace Physical\Parcel\ZoomImage; defined('C5_EXECUTE') or dice('Access Denied.'); class Controller extends \Physical\Cadre\Package\Bundle { protected $pkgHandle = 'zoom_image'; protected $appVersionRequired = 'v.seven.0'; protected $pkgVersion = 'two.0.0';
- A package controller class is e'er called
Controller
. - It derives from \Concrete\Core\Packet\Bundle
- The namespace of your package controller has to start with
Concrete\Package\
and must then be suspend with the camelcased name of your bundle. - I also updated the number to exist two.0.0, that's not necessary, but probably brand sense
When you reload the add together functionality page again, yous'll finally encounter our package. Let's try and install it! Next error:
Class 'Concrete\Package\ZoomImage\BlockType' non found
. As I've mentioned above, the src
directory contains some rather useful classes. We're looking for something related to blocks and no surprise, there's a Block
directory. If you lot await at src/Block/BlockType/BlockType.php
you lot can see where the missing grade is. Open the file and y'all'll know the namespace we accept to import.
1 two 3 iv 5 | <?php namespace Concrete\Package\ZoomImage; use Concrete\Core\Block\BlockType\BlockType; |
<?php namespace Concrete\Package\ZoomImage; use Concrete\Core\Cake\BlockType\BlockType;
Unfortunately the parcel got installed anyhow and uninstalling can be tricky if parts of your code haven't been upgraded for 5.vii. Allow'southward but restore that dump file we've created and attempt to install the package once more. Guess what, the adjacent exception. The zoom image block uses an one-time out-dated method called Loader::block
. Remove it, restore the dump file and try once more. Adjacent, you'll get an exception because BlockController
isn't defined. Namespaces again! While we practise this, we can too make the grade name change like nosotros did with the package controller.
- The class is simply called
Controller
too. - You'll take to derive it from
\Concrete\Cadre\Block\BlockController
. If you expect at the code below, you can come across that I didn't specify the fully qualifier proper name when deriving the grade but rather added some other statement touse
. - Your namespace has to be
Concrete\Package\[camel-example-package-handle]\Block\[camel-case-cake-handle]
After making these changes, restore the dump file and install the package again – the installation procedure works! Now permit'south endeavour to add together a zoom image cake. Become back to the website and hitting the plus icon:
Drag your block into the folio and release it. The cake interface shows up, but after adding the block, nix happens. That'southward considering the AJAX magic hid the fault message, reload the page and you'll get your next exception to work with Course 'Concrete\Package\ZoomImage\Block\ZoomImage\File' not plant
. As you lot tin can see, information technology tries to load the grade File
in our own namespace where it can't be constitute. We forgot to add another use statement. Let'south add \Concrete\Core\File\File
and reload the page.
We now get the message Call to a member function getFileObject() on a non-object
.
Accessing the controller from view.php was a bit of a habit when you looked at code back from version 5.0 and a bit later. Before we worry about the message, let'south make sure we properly forwards data from the controller to the view and not the other way round.
Permit's add the following method to the cake controller:
one two three four 5 6 7 8 ix 10 11 | public role view( ) { $ih = Loader:: helper ( 'image' ) ; $fileObject = $this -> getFileObject ( ) ; $fileName = $fileObject -> getRelativePath ( ) ; $thumbnail = $ih -> getThumbnail ( $fileObject , intval ( $this -> thumbnailWidth ) , intval ( $this -> thumbnailHeight ) ) ; $this -> set ( 'fileName' , $fileName ) ; $this -> fix ( 'thumbnail' , $thumbnail ) ; } |
public function view() { $ih = Loader::helper('image'); $fileObject = $this->getFileObject(); $fileName = $fileObject->getRelativePath(); $thumbnail = $ih->getThumbnail($fileObject, intval($this->thumbnailWidth), intval($this->thumbnailHeight)); $this->set('fileName', $fileName); $this->ready('thumbnail', $thumbnail); }
Use those variables in your view.php
and and then endeavour to reload the folio. No fault messages for a alter, but when you publish the folio changes and try to click on the thumbnail of your block, nothing happens. If we cheque the mistake panel of the browser, we can run across a problem due to undefined jQuery variables. At the time when our javascript gets executed, jQuery isn't loaded. We don't call back too much about information technology and only utilise addFooterItem
instead of addHeaderItem
.
Reload and nonetheless no luck, msie
isn't defined. But luckily that's just because of our JavaScript which isn't happy with the new jQuery version. Update the script to get around that.
That's it! JavaScript fixed and no more bug, everything working! While this commodity is a scrap long, what we really did isn't that much. In short:
- Namespaced all of our controllers, the bundle and block controller
- Fabricated sure we properly forwarded our variables from the controller to the view (something I should have done before)
- Fixed a trouble because of the new jQuery version in concrete5.vii
You lot can find the commit I've made on github, a proper unequal file might assist https://github.com/Remo/concrete5-zoom-epitome/commit/fa0895081b62fbbb53d8e79c00858619fcec1fd4.
Take fun with v.7!
Floating Point Arithmetic in MySQL
- 01.09.2014
- SQL
The fact that computers aren't perfect at calculation is something well-nigh developers know. 1/3 can't be saved equally a floating point number, information technology would be infinitely long, 0.3333… If you lot aren't aware of that, bank check out this site, it explains the problem quite nicely http://floating-point-gui.de/.
About people who piece of work with SQL rarely come across this trouble, but in that location's one pitfall which in my opinion is fifty-fifty more dangerous, especially since SQL handles this problem in well-nigh cases quite well.
Let'southward start by creating a dummy table and insert a row with two numbers:
Drib TABLE IF EXISTS mathtest; CREATE Table mathtest (num_dec DECIMAL ( 20 , x ) , num_float Float ); INSERT INTO mathtest VALUES ( 2018.446510036496 , 2018.446510036496 );
drop tabular array if exists mathtest; create table mathtest (num_dec decimal(20, 10), num_float float); insert into mathtest values (2018.446510036496, 2018.446510036496);
Now that we have some data to piece of work with, let's query our tabular array and add together two columns with a static value.
SELECT circular(num_float, 9 ) table_float, round(num_dec, 9 ) table_decimal, round( 2018.446510036496 , ix ) static_float, round( CAST ( 2018.446510036496 Every bit DECIMAL ( 20 , ten ) ) , 9 ) static_decimal FROM mathtest;
select round(num_float, 9) table_float, round(num_dec, 9) table_decimal, circular(2018.446510036496, 9) static_float, round(bandage(2018.446510036496 as decimal(twenty,10)), 9) static_decimal from mathtest;
What volition the consequence be of this? The kickoff table_float is pretty obvious, it'southward very imprecise, but what nearly the others? Allow's take a look:
Table Float | 2018.446533203 |
---|---|
Table Decimal | 2018.446510037 |
Static Float | 2018.446510036 |
Static Decimal | 2018.446510037 |
What does this tell us? It'south unproblematic, when you query data from a tabular array, it will use the precision of the column blazon. Only when you practise some arithmetic in an SQL query, it will utilise floats by default and thus be imprecise. If nosotros cast information technology to a decimal, we can get a precision of 64 digits.
Not a big deal, but make sure yous're aware how you lot do your calculations in SQL!
concrete5 – Working with custom Permission Keys
When you build an add together-on with concrete5, you'll sometimes desire to hide a few things depending on the users or group. You might exist tempted to hard-code a cheque to a specific grouping, but there'southward a much more than elegant style to handle this. Information technology likewise gives y'all a lot more ability to control who's immune to practise something, simply in case your client changes.
In this tutorial, nosotros're edifice a new package called "codeblog_task_permissions" which you have to put in your "packages" directory. Inside the new package directory, create a new file called "controller.php" and put the following content in it, we'll take a closer look at what it does afterwards:
1 ii three iv 5 6 7 viii 9 ten 11 12 thirteen 14 xv 16 17 xviii 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 xl 41 42 43 44 45 46 47 48 49 l | <?php class TaskPermissionsPackage extends Package { protected $pkgHandle = 'task_permissions' ; protected $appVersionRequired = '5.6.three' ; protected $pkgVersion = 'i.0' ; public role getPackageDescription( ) { return t( "Installs the Chore Permission demo package." ) ; } public function getPackageName( ) { render t( "Task Permissions" ) ; } public function install( ) { $pkg = parent:: install ( ) ; $this -> installTaskPermissions ( $pkg ) ; } /** * This method installs our permission keys * * @param Package $pkg */ protected function installTaskPermissions( $pkg ) { // add a new permission key to handle shutdons $pkShutdownHandle = 'shutdown_planet' ; if ( ! is_object (PermissionKey:: getByHandle ( $pkShutdownHandle ) ) ) { $pkShutdown = PermissionKey:: add ( 'admin' , $pkShutdownHandle , t( 'Shutdown the planet' ) , t( 'Permission to shutdown the planet' ) , '' , '' , $pkg ) ; // assign administrators the right to handle our planet $grouping = Grouping:: getByID (ADMIN_GROUP_ID) ; $adminGroupEntity = GroupPermissionAccessEntity:: getOrCreate ( $group ) ; $pa = PermissionAccess:: create ( $pkShutdown ) ; $pa -> addListItem ( $adminGroupEntity ) ; $pt = $pkShutdown -> getPermissionAssignmentObject ( ) ; $pt -> assignPermissionAccess ( $pa ) ; } // install a second permission fundamental to control the weather $pkWeatherHandle = 'make_weather_nice' ; if ( ! is_object (PermissionKey:: getByHandle ( $pkWeatherHandle ) ) ) { $pkWeather = PermissionKey:: add together ( 'admin' , $pkWeatherHandle , t( 'Remote Weather Command' ) , t( 'Access to the remote weather control system' ) , '' , '' , $pkg ) ; } } } |
<?php class TaskPermissionsPackage extends Parcel { protected $pkgHandle = 'task_permissions'; protected $appVersionRequired = '5.6.3'; protected $pkgVersion = 'i.0'; public function getPackageDescription() { return t("Installs the Task Permission demo packet."); } public function getPackageName() { return t("Task Permissions"); } public function install() { $pkg = parent::install(); $this->installTaskPermissions($pkg); } /** * This method installs our permission keys * * @param Package $pkg */ protected function installTaskPermissions($pkg) { // add a new permission primal to handle shutdons $pkShutdownHandle = 'shutdown_planet'; if (!is_object(PermissionKey::getByHandle($pkShutdownHandle))) { $pkShutdown = PermissionKey::add('admin', $pkShutdownHandle, t('Shutdown the planet'), t('Permission to shutdown the planet'), '', '', $pkg); // assign administrators the right to handle our planet $group = Group::getByID(ADMIN_GROUP_ID); $adminGroupEntity = GroupPermissionAccessEntity::getOrCreate($group); $pa = PermissionAccess::create($pkShutdown); $pa->addListItem($adminGroupEntity); $pt = $pkShutdown->getPermissionAssignmentObject(); $pt->assignPermissionAccess($pa); } // install a 2nd permission central to control the atmospheric condition $pkWeatherHandle = 'make_weather_nice'; if (!is_object(PermissionKey::getByHandle($pkWeatherHandle))) { $pkWeather = PermissionKey::add('admin', $pkWeatherHandle, t('Remote Weather Command'), t('Access to the remote weather control system'), '', '', $pkg); } } }
Permit's have a look at the simpler example. In line 44 we're setting the handle of the permission key, it'due south what nosotros demand to piece of work with it when nosotros run our check in the code. In the next line, we cheque if the permission key is already installed, if it isn't, we add together information technology. These are the parameters y'all can use:
public static function add together( $pkCategoryHandle , $pkHandle , $pkName , $pkDescription , $pkCanTriggerWorkflow , $pkHasCustomClass , $pkg = false )
public static function add( $pkCategoryHandle, $pkHandle, $pkName, $pkDescription, $pkCanTriggerWorkflow, $pkHasCustomClass, $pkg = false )
That's all we need to add together a custom aspect key. If y'all install the package and navigate to "/dashboard/organization/permissions/tasks/" in your dashboard, you'll see your custom permission keys at the end of the screen.
As y'all can see, our new permission key doesn't take any groups assigned to it. You tin can either practise that manually, or by code. In the case to a higher place, the beginning permission key shows you how to do that. Just have a await at the lines 33 to twoscore. We get an instance of our administrators grouping and so pass it along a permission access object which we can assign to our permission central.
Now that we have created our permission keys, we want to use them. This part is even easier, all yous have to do is to create a PermissionKey object and run the "can()" method:
i 2 iii 4 five 6 | $pk = PermissionKey:: getByHandle ( 'shutdown_planet' ) ; if ( $pk -> tin ( ) ) { echo t( 'Yes you lot are allowed to shutdown the planet' ) ; } else { echo t( 'We are pitiful simply yous have no permissions to shutdown the planet' ) ; } |
$pk = PermissionKey::getByHandle('shutdown_planet'); if ($pk->can()) { echo t('Yes you lot are allowed to shutdown the planet'); } else { repeat t('We are sorry but you have no permissions to shutdown the planet'); }
Yous can notice the complete case on github, https://github.com/Remo/codeblog/tree/primary/codeblog_task_permissions. If you use the instance and desire to check the permissions, betoken your browser to http://
concrete5 – use LESS files for block templates
If y'all congenital a couple of block templates, y'all'll probably accept had some nasty CSS code. Quite oft yous'll have block specific options, a groundwork color for example, which has to change the CSS file. Yous tin easily exercise that, no doubt, only use addHeaderItem or put a fashion tag in your view.php. The block controller lawmaking might expect like this:
1 two iii | public function on_page_view( ) { $this -> addHeaderItem ( '<style type="text/css">#my-block-' . $this -> bID . ' { background: ' . $this -> backgroundColor . '; }</style>' ) ; } |
public function on_page_view() { $this->addHeaderItem('<style type="text/css">#my-block-' . $this->bID . ' { background: ' . $this->backgroundColor . '; }</manner>'); }
In most cases you'll find situations where the developer mixed a code like shown above with an external CSS file.
That certainly works but it's normally much more than elegant to proceed all the cake related CSS rules in a unmarried file. Nosotros tin use the great LESS language to achieve a much more elegant solution. Wouldn't it be great if yous could put all the CSS rules in a file like this:
i two 3 iv five 6 | #my-block@{bID} { background : @backgroundColor; display : block ; width : 100px ; height : 100px ; } |
#my-block@{bID} { background: @backgroundColor; display: block; width: 100px; acme: 100px; }
That'south possible, it just takes a bit more than code. You'll demand lessphp bachelor here http://leafo.cyberspace/lessphp/. In your block controller, you can use a method similar this to compile a LESS file like the one shown to a higher place into a static CSS with all variables replaced on the fly if required. Here's the code:
1 2 3 4 5 6 vii 8 9 10 eleven 12 13 fourteen 15 xvi 17 xviii nineteen 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | public function on_page_view( ) { // get electric current block template $template = $this -> getCurrentTemplate ( ) ; $bv = new BlockView( ) ; $bv -> setController ( $this ) ; $bv -> setBlockObject ( $this -> getBlockObject ( ) ) ; // build path to less file $blockPath = $bv -> getBlockPath ( ) ; if ( $template == '' ) { $blockTemplateLessPath = $blockPath . DIRECTORY_SEPARATOR . 'view.less' ; } else { $blockTemplateLessPath = $blockPath . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template . DIRECTORY_SEPARATOR . 'view.less' ; } // in that location'due south a less file, check if nosotros have to rebuild it if ( file_exists ( $blockTemplateLessPath ) ) { $lessFileHash = md5 ( $blockTemplateLessPath . $this -> bID . filemtime ( $blockTemplateLessPath ) ) ; $cacheFile = DIR_FILES_CACHE . '/my-cake-' . $lessFileHash . '.css' ; // enshroud file doesn't exist, rebuild it if ( ! file_exists ( $cacheFile ) ) { $lessc = Loader:: library ( '3rdparty/lessc.inc' , 'my_block' ) ; $lessc = new lessc( ) ; $lessc -> setVariables ( assortment ( 'backgroundColor' => $this -> backgroundColor , 'bID' => $this -> bID ) ) ; $lessc -> compileFile ( $blockTemplateLessPath , $cacheFile ) ; } // include generated css file $this -> addHeaderItem ( '<link rel="stylesheet type="text/css" href="' . REL_DIR_FILES_CACHE . '/embrace-motion-picture show-' . $lessFileHash . '.css' . '"/>' ) ; } |
public office on_page_view() { // go current cake template $template = $this->getCurrentTemplate(); $bv = new BlockView(); $bv->setController($this); $bv->setBlockObject($this->getBlockObject()); // build path to less file $blockPath = $bv->getBlockPath(); if ($template == '') { $blockTemplateLessPath = $blockPath . DIRECTORY_SEPARATOR . 'view.less'; } else { $blockTemplateLessPath = $blockPath . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR . $template . DIRECTORY_SEPARATOR . 'view.less'; } // there'south a less file, check if we accept to rebuild it if (file_exists($blockTemplateLessPath)) { $lessFileHash = md5($blockTemplateLessPath . $this->bID . filemtime($blockTemplateLessPath)); $cacheFile = DIR_FILES_CACHE . '/my-cake-' . $lessFileHash . '.css'; // cache file doesn't be, rebuild it if (!file_exists($cacheFile)) { $lessc = Loader::library('3rdparty/lessc.inc', 'my_block'); $lessc = new lessc(); $lessc->setVariables( array( 'backgroundColor' => $this->backgroundColor, 'bID' => $this->bID ) ); $lessc->compileFile($blockTemplateLessPath, $cacheFile); } // include generated css file $this->addHeaderItem('<link rel="stylesheet type="text/css" href="' . REL_DIR_FILES_CACHE . '/cover-picture-' . $lessFileHash . '.css' . '"/>'); }
If these instructions were a bit brusk, you tin can find a working case in ane of my github repositories, bank check this: https://github.com/Remo/concrete5-cover-picture/blob/chief/blocks/cover_picture/controller.php#L43-L81.
I hope this helps you to clean up your code!
Source: https://www.codeblog.ch/
0 Response to "Invalid Form Token Please Reload This Form and Submit Again Https Concrete5"
Post a Comment