I’ve previously created a very simple module for SuiteCRM which adds coloured logging (SuiteCRM Colour Logger). I’ve now expanded it somewhat to add extra features.
It’s now called SuiteSuperLogger and allows specifying the log format in the config.
Enabling coloured logging can be done by adding
$sugar_config['suitesuperlogger']['colour'] = true;
To the config.
Altering the log format can be done by adding the following to
$sugar_config['suitesuperlogger']['format'] = ':date:[:pid:][:userId:][:level:][:remoteAddr:][:forwardedAddr:][:requestMethod:]:msg:';
The following placeholders are accepted and will be replaced with an appropriate value:
- The date the message was logged
- The process id
- The logged in user id
- The log level
- The remote address as found in the PHP $_SERVER superglobal.
- The HTTP X FORWARDED FOR header
- The request method (i.e. GET, POST, e.t.c.)
- The actual log message
With the release of SuiteCRM 7.3 comes Alerts. These are displayed within SuiteCRM as a small badge in the menu bar. I.e:
Since these are just stored as beans we can add notifications by simply creating a new record with the appropriate values and saving it. For example:
Calling this can be used to create an alert for a specific user like so:
The CLI to php allows checking for syntax errors using
php -l I’ve created a very basic script which will recursively check folders for php files with syntax errors. It’s intended to quickly show syntax errors in a large application. It’s available here: https://github.com/JimMackin/PHPSyntaxCheck
Simply run it and pass the path to your app:
php phpsyntaxcheck.php /path/to/php/files
Sometimes when you create a new module you want it to appear in the “Related To” dropdowns around SuiteCRM. This post will cover the simple method of adding modules to these dropdowns.
In this post we’ll add a fictional “Sport” module to the dropdown. We’ll end up with this:
The related to dropdown, like most in SuiteCRM can be changed by using the dropdown editor within SuiteCRM. We’re going to use the dropdown editor to add our custom module.
If you want to target the Related To module in Notes then edit the record_type_display_notes dropdown. For other related to dropdowns edit the parent_type_display.
We start by adding a new entry to the dropdown with the modules name as the “Item Name” and the display label we wish to use as the “Display Label”. I.e. in our example we’ll have
“ABC_Sport” as the “Item Name” and “Sport” as the “Display Label” as in this image:
And that’s it! SuiteCRM will use the module name to load the correct popup when searching for the module and will store this when saving the record. Your custom module can now be added to notes and the like.
If you’ve created a custom module but are getting the message “Imports aren’t set up for this module type” then it’s very easy to add this functionality to your custom module.
In the bean file
modules/ABC_Your_Module/ABC_Your_Module.php simply add the line
var $importable = true;
After the class definition and you’ll be able to import this module.
If you move instances of SuiteCRM around it’s possible to have a copy of the SuiteCRM files that reference a custom field that doesn’t exist in the
This can cause broken SQL queries since SuiteCRM will try to reference a field but won’t have it’s name. A broken query may look something like:
UPDATE my_custom_module SET name='Foo', =NULL,=NULL WHERE id='1234';
This can be fixed in one of two ways.
The first, preferred way is to get the info from the fields_meta_data table. This mysqldump command will create a file with the fields meta data:
mysqldump -uYourDBUser --insert-ignore --no-create-info -p YourDB fields_meta_data > fields_meta_data.sql
This can then be used to populate the new DB:
mysql -uYourDBUser -p YourNewDB < fields_meta_data.sql
The second is to find and remove the fields which are causing the issue. The following script will list any entries in the vardefs without a name which causes the original broken queries. Simply change the $base variable to be the path to the SuiteCRM instance you want to check and run
php -f fieldcheck.php:
Once you have found the offending fields you can remove the definitions for them.
A previous post covered adding a button to the List View. However this was adding an action button to the list as a whole. This post will cover adding buttons for each row.
By the end of this post you will be able to add buttons such as this one:
Our example will look at the calls module. We’ll add a simple button to view the call on the calendar.
First off we will create a new non-db field in the calls module. We add the following file to
custom/Extension/modules/Calls/Ext/Vardefs/ViewOnCalButton.php (we use the filename ‘ViewOnCalButton.php’ but this can be whatever you wish).
Next we add the language string for our new field. We place this file in
In order to actually have the field display as a button we set up a logic hook to fill in the value. First we must define the logic hook in
And then implement the hook itself and add it to
Note that we are creating a button which links to the calendar but this can do whatever actions you require. We must do a quick repair and rebuild from the admin menu in order for our changes above to take effect.
Finally we add the button to the list view. This can either be done in studio or by editing the list view defs. Let’s do this through studio:
And there we have it. We now have the following:
Upon clicking we should be taken to the calendar.
Note that the above button is just an example and has a few issues that could be improved upon. If we click “View on calendar” for a call that isn’t ours we will be taken to a calendar page without the call on it. Can you see any other improvements? Let me know in the comments,
Me and my wife occasionally play a simple game when on longer car journeys. In the UK the last 3 characters in a car registration plate are letters.
The aim of the game is to come up with words which start with the first letter, end with the last letter and contain the middle letter. So for the example plate in the image above we’d use SMR, a word that we could choose would be ‘speedometer (since it starts with s, ends with r and contains m’). Computers, unsurprisingly, are very good at this. Here’s an example of a super simple python script which prints matching words (this assumes you are on a Linux system, or at least a system with
It can be called using
python reg_plate_game.py "BD51 SMR". This example outputs the following:
salamander samovar sampler scamper scandalmonger schemer schmaltzier schoolmaster scimitar scoutmaster scrambler scummier seamier seemlier semester semicircular semiconductor seminar semitrailer shimmer shoemaker similar simmer simper simpler simulator skimpier slammer sledgehammer slimier slimmer slumber slummer smacker smaller smarmier smarter smear smellier smelter smoggier smoker smokier smolder smoother smother smoulder smudgier smugger smuggler smuttier solemner somber spammer speedometer squirmier stammer stammerer steamer steamier steamroller stepmother stormier streamer stumbler stumpier sublimer submitter summer summerier summoner supercomputer swampier swimmer sympathizer
It’s possible to add your own action menu items to the List view. By the end of this post you’ll be able to add your own menu items like this one:
In our case we’ll be adding this to the “Calls” list view.
First off we add the string for the menu item text. In this case “New action”. We place this into `custom/Extension/modules/Calls/Ext/Language/en_us.CustomMenuAction.php` (the `CustomMenuAction` part can be anything you like.
Next we create a new custom list view for the calls module and place this in `custom/modules/Calls/views/view.list.php` (customising views can be found in my SuiteCRM book).
This does the actual work of adding the button. This adds a new bit of HTML to the array `$this->lv->actionsMenuExtraItems`. SuiteCRM will then pick this up and add this to the list of action buttons.
In this case the button just points to a new entry point `myNewEntryPoint`. Adding entry points will be covered in a future post (if you are impatient you can always checkout my SuiteCRM book).
Chase the ace is a simple card game that I was taught when I was younger from my dad. Recently on holiday I was playing with some friends and for a few games it was always the dealer that was put out of the game first. We’d noticed this before and has dubbed it “The curse of the dealer”. I was curious to see if the curse had any basis or if it was just chance.
For those of you not familiar with Chase the Ace it is the simplest card game I know. Each player is dealt a card (the more players the better!). Play starts to the left of the dealer with each player deciding whether to keep his current card or to force the player on their left to swap with them. When play reaches the dealer they can choose to swap with the deck. After every player has had their turn the person (or persons) with the lowest card (Aces are low) is knocked out of the game. The next round starts again without the losing players until a player remains (or all players are knocked out).
Testing the curse
I created a simple python script to play a bunch of hands with 10 players and keep track of which player or players were knocked out first (the source of which can be found on GitHub.
The strategy played is pretty simple (so it may affect the outcome) and uses the following rules:
- If a player swaps with us and we end up with a higher card then we always keep that card (since we are guaranteed to stay in).
- If we have a card higher than a 7 keep it.
- Otherwise swap.
Using 10 players for 10,000,000 hands gave the following results:
We can see that the dealer is indeed at a disadvantage and, in fact your odds of losing decreases as you get closer to early positions. I suspect that this is due to bad cards “bubbling up” through the positions. If you have a high card and are in later position you have a higher chance of losing it. I may revisit this code at some point and see if this code can be reused to generate an optional strategy.
Edit: Someone has pointed out that, in fact, it’s the second to last player that loses slightly more. I’m rerunning this with more games to see if this is chance or not – there may be a point where all players are equally disadvantaged.