In C, there is a nice function that converts strings to integers without throwing exceptions. I use atoi all of the time. In C#, I have used the convert class for a long time in order to accomplish a similar task. The only I always had with it, is that it throws and exception of "Input string was not in a correct format" if the string is not a number. That really is not an efficient way of handling the conversion especially if you are doing multiple of them and the performance.
There is a method in the structure for each type of number called TryParse. This method will try to convert the number and return a bool value on whether it did or not. It is much more efficient at handling potential errors. Below, I have put an example that shows both ways of converting.
using System;
class Program
{
static string X = "99";
static string Y = "X1";
static void Main(string[] args)
{
//call the functions for each string and see what we get
int retval = 0;
retval = use_convert(X);
retval = use_try_parse(X);
retval = use_convert(Y);
retval = use_try_parse(Y);
}
static int use_convert(string theVal)
{
int A = 0;
try
{
A = Convert.ToInt32(theVal);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return A;
}
static int use_try_parse(string theVal)
{
int A = 0;
bool isConverted;
try
{
isConverted = Int32.TryParse(theVal, out A);
if (!isConverted)
Console.WriteLine("Did not convert number");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return A;
}
}
In the above example, you can see how the 2 methods work and what they will return for each string.
WatchCat Bytes
This blog contains posts of information that have helped us with some tasks. We have posted them to help remind us of how to do them. Maybe it will also help somebody else, as well.
Friday, May 18, 2012
Friday, March 30, 2012
Doing a Sum on a Subset in MySQL
Sometimes I need to sum up a subset of values from a table for a certain column. For instance, I may have a table names TABLE and a column that contains is an int and is labeled numberTries. I may also have another column that is an auto-increment column (int) labeled rownum. I would like to see the sum of the number of tries for the last 10 rows. In order to do this, you have to create a query like the following:
SELECT SUM(numberTries) FROM (SELECT numberTries FROM TABLE ORDER BY rownum DESC LIMIT 10) as subquery;
Notice that I have the query to get the rows that we need wrapped by the query to sum up the rows for column numberTries.
One other thing we can do is find out the number of rows that were actually added in there. If there were not 10 rows, then only the amount that were in the database would have been summed up.
Here is the query to get that number back:
SELECT SUM(numberTries), COUNT(*) FROM (SELECT numberTries FROM TABLE ORDER BY rownum DESC LIMIT 10) as subquery;
SELECT SUM(numberTries) FROM (SELECT numberTries FROM TABLE ORDER BY rownum DESC LIMIT 10) as subquery;
Notice that I have the query to get the rows that we need wrapped by the query to sum up the rows for column numberTries.
One other thing we can do is find out the number of rows that were actually added in there. If there were not 10 rows, then only the amount that were in the database would have been summed up.
Here is the query to get that number back:
SELECT SUM(numberTries), COUNT(*) FROM (SELECT numberTries FROM TABLE ORDER BY rownum DESC LIMIT 10) as subquery;
Using Limit in MySQL
There are times when you would like to limit the results coming back on a query to certain amount of records. For instance, if I need to see the last 10 records in a table, I could use the following query:
SELECT * FROM TABLE ORDER BY rownum DESC LIMIT 10;
The previous line would order the records in the table by the row number is descending order and return only the last 10 in the table. Simple enough.
Now, let's say that we want to get back the 11th-20th records. We can use LIMIT for this purpose as well. This would be the query for that:
SELECT * FROM TABLE ORDER BY rownum DESC LIMIT 10,10;
So, the LIMIT keyword can be very useful in getting subsets back for queries.
SELECT * FROM TABLE ORDER BY rownum DESC LIMIT 10;
The previous line would order the records in the table by the row number is descending order and return only the last 10 in the table. Simple enough.
Now, let's say that we want to get back the 11th-20th records. We can use LIMIT for this purpose as well. This would be the query for that:
SELECT * FROM TABLE ORDER BY rownum DESC LIMIT 10,10;
So, the LIMIT keyword can be very useful in getting subsets back for queries.
Thursday, March 29, 2012
Crontab Line Syntax
Every time that I am setting up a new job in crontab, I have to go look up the syntax for the parameters for the lines. I can never remember the order of the parameters. So, here they are:
* * * * *
| | | | |
| | | | ---------- day of week (0 - 6) Sunday is day 0
| | | ------------- month (1 - 12)
| | ---------------- day of month (1 - 31)
| ------------------- hour (0 - 23)
----------------------- minute (0 - 59)
An example line would be the following:
30 5 * * 1-5 /etc/run.me
This app would run at 5:30 AM every Mon - Fri
Another example would be the following:
0,15,30,45 * * * * /etc/run2.me
This app would run every 15 minutes all of the time.
* * * * *
| | | | |
| | | | ---------- day of week (0 - 6) Sunday is day 0
| | | ------------- month (1 - 12)
| | ---------------- day of month (1 - 31)
| ------------------- hour (0 - 23)
----------------------- minute (0 - 59)
An example line would be the following:
30 5 * * 1-5 /etc/run.me
This app would run at 5:30 AM every Mon - Fri
Another example would be the following:
0,15,30,45 * * * * /etc/run2.me
This app would run every 15 minutes all of the time.
Sunday, January 22, 2012
Setting Up a Custom Domain Email Address from Gmail on Kindle Fire
My boys have a Kindle Fire and I wanted to setup their email on it. So, I had to figure out how to use the Email App that Amazon provides with a "Gmail" account that is not using Gmail as the domain. For most Android devices, this is easy. This was not the easiest thing at first for the Fire, but here are the steps I took in order to do it. First off, I use IMAP for checking email since we check email in multiple places. So these instructions will be directed to dealing with IMAP.
1. Make sure you have IMAP turned on in your Gmail account settings by checking using a browser and logging into your email via the Gmail website.
2. Open the email app form the Kindle.
3. Choose Gmail as your email provider.
4. Type in your email address and password. For instance, Jason@example.com would be my email address and my password would be password.
5. When it asks what type of account it is, choose IMAP.
6. The next screen will have information filled in, but it will be wrong. Make the following changes:
Username: Your full email address
IMAP Server: imap.gmail.com
Secuirty type: SSL
7. Now the next screen will ask for the outgoing server settings. Make the following changes:
SMTP Server: smtp.gmail.com
Security type: TLS
That should be all of the changes you need.
1. Make sure you have IMAP turned on in your Gmail account settings by checking using a browser and logging into your email via the Gmail website.
2. Open the email app form the Kindle.
3. Choose Gmail as your email provider.
4. Type in your email address and password. For instance, Jason@example.com would be my email address and my password would be password.
5. When it asks what type of account it is, choose IMAP.
6. The next screen will have information filled in, but it will be wrong. Make the following changes:
Username: Your full email address
IMAP Server: imap.gmail.com
Secuirty type: SSL
7. Now the next screen will ask for the outgoing server settings. Make the following changes:
SMTP Server: smtp.gmail.com
Security type: TLS
That should be all of the changes you need.
Friday, January 20, 2012
PHP and GMT
I have to deal with financial data a bunch and one of the issues that I often run into is dealing with time issues especially when dealing with FIX messages. A nice function I have found that helps to deal with handling time conversion in PHP is gmstrftime. This function converts time to Greenwich Mean Time from your current time zone. So, you do not have to worry about doing the conversion yourself for the time. Here is an example.
date_default_timezone_set('America/New_York');
$cur_time = mktime(22, 0, 0, 12, 31, 2011);
echo strftime("%b %d %Y %H:%M:%S", $cur_time) . "\n";
echo gmstrftime("%b %d %Y %H:%M:%S", $cur_time) . "\n";
This code will output the following:
Dec 31 2011 22:00:00
Jan 01 2012 03:00:00
So, for easy GMT conversion, PHP has you covered.
Tuesday, November 15, 2011
Illegal Mix of Collations Error in MySQL
I was doing a join statement in MySQL and had an error popup that I had not seen before. The error i received was the following:
Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
Since I am trying to keep data segregated, I created a separate database from the one that SugarCRM had created in MySQL and created my own table. It appears that the 2 table has different collation defaults on them. I had no idea that was the case. In order to examine that for each table, I ran the following command:
SHOW CREATE TABLE tblname
This gave me the information I needed. for each table. One of my tables showed
COLLATE = 'utf8_unicode_ci'
while the other one did not have a collate value on it. For me, this meant hat the value was
COLLATE = 'utf8_general_ci'
So, I needed to change the default database collate type for one of them. I decided to change it to utf8_general_ci and did so with the following command:
ALTER DATABASE dbname COLLATE = 'utf8_general_ci';
I then needed to chance my table. So, I did this by dropping my table and recreating it.
Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
Since I am trying to keep data segregated, I created a separate database from the one that SugarCRM had created in MySQL and created my own table. It appears that the 2 table has different collation defaults on them. I had no idea that was the case. In order to examine that for each table, I ran the following command:
SHOW CREATE TABLE tblname
This gave me the information I needed. for each table. One of my tables showed
COLLATE = 'utf8_unicode_ci'
while the other one did not have a collate value on it. For me, this meant hat the value was
COLLATE = 'utf8_general_ci'
So, I needed to change the default database collate type for one of them. I decided to change it to utf8_general_ci and did so with the following command:
ALTER DATABASE dbname COLLATE = 'utf8_general_ci';
I then needed to chance my table. So, I did this by dropping my table and recreating it.
Thursday, November 10, 2011
Turning iGoogle On
I was working with Google Sites and needed to make a Google Gadget. An easy way to store them is to use the Google Development which utilizes iGoogle to save the gadgets. When I tried to use this feature, I was told that iGoogle was not enabled for the domain that was setup. Since I was the administrator, I knew I had not turned it off. I had a hard time figuring out exactly how to enable this feature. I finally figured it out and wanted to document it here. In order to enable iGoogle for a domain in Google Sites do the following:
Once you have done this you will have iGoogle enabled and be able to do what you need to do with it.
- Login to Google Sites at https://www.google.com/a/cpanel/YOURDOMAIN/
- Click on the Organization & users tab
- Click on the Services sub-tab
- Scroll down to the iGoogle row
- Change the switch from OFF to ON
- Click on Save Changes
Once you have done this you will have iGoogle enabled and be able to do what you need to do with it.
Tuesday, November 8, 2011
Create an SSH Tunnel
Sometimes it is necessary to create a tunnel in order to access a port on a remote box from your local box and there is a firewall preventing you from reaching it. As long as you have access to SSH, you can access this port. In order to do so, just use the following command:
ssh -N user@remote-server -L localport/localhost/remoteport
The -N switch is used so commands are not executed on the remote system. Now, if you are having issues keeping the tunnel open due to lack of traffic, you can change the line to the following:
ssh -N user@remote-server -o ServerAliveInterval=15 -L localport/localhost/remoteport
This will then generate a heartbeat every 15 seconds so the tunnel will remain up.
ssh -N user@remote-server -L localport/localhost/remoteport
The -N switch is used so commands are not executed on the remote system. Now, if you are having issues keeping the tunnel open due to lack of traffic, you can change the line to the following:
ssh -N user@remote-server -o ServerAliveInterval=15 -L localport/localhost/remoteport
This will then generate a heartbeat every 15 seconds so the tunnel will remain up.
Monday, November 7, 2011
Issue with Delivery of Gmail Due to SPF Record
A couple of days ago I had a group that had been receiving email from me just fine from my business email account. I use a Gmail hosted account for it. All of a sudden, they were not able to receive my email anymore. I received the following message:
This is an automatically generated Delivery Status
Notification
THIS IS A WARNING MESSAGE ONLY.
YOU DO NOT NEED TO RESEND YOUR MESSAGE.
Delivery to the following recipient has been delayed:
emailaddress@emailaddress.com
Message will be retried for 2 more day(s)
Technical details of temporary failure:
Unspecified Error (SENT_MESSAGE): Connection timed out
With their help, I was able to figure out that they were not accepting my email because I did not have an SPF record for my domain. So, I went to add one, and it resolved the issue immediately.
What is an SPF Record
SPF stands for sender policy framework and is used to try to prevent spam. You can read all about it here. Basically, it allows the owner of a domain to specify the IP address that email will be coming from.
Since I had DNS hosted at GoDaddy and my email hosted at Gmail, I needed to figure out exactly what to put into the record. Here is a link to the steps required to set the information up correctly.
Wednesday, November 2, 2011
Keep an SSH Connection Open Through Even During Dormant Times
If you manage any Linux servers over the internet through ssh, you may have experienced your client disconnecting after times of inactivity. I know I do and it annoys me to death. There is a parameter you can add to the ssh connection in order to keep it up over these type of connections. Just do the following:
ssh -o ServerAliveInterval=15 login@servername
The parameter -o ServerAliveInterval=15 adds the functionality of sending a heartbeat type message to the server every 15 seconds if data has not been sent in the last 15 seconds. This parameter is customizable.
ssh -o ServerAliveInterval=15 login@servername
The parameter -o ServerAliveInterval=15 adds the functionality of sending a heartbeat type message to the server every 15 seconds if data has not been sent in the last 15 seconds. This parameter is customizable.
Creating a Trusted SSH Connection
Sometimes I have a need to script out an ssh session and do not want to be prompted for a password when the connection is established. So, I have to create a trusted connection between the 2 boxes. I am going to assume that I am logged in as root, but you can do this as any user. Just replace root with the username in the directions below. In order to do this, the following steps should be taken:
- On the local host, go to the following directory /root/.ssh/
- Run the following command in order to generate a file that contains the key you will need: ssh-keygen -t ds
- When prompted for what file to save the key, you can just leave the default which is what we will use, /root/.ssh/id_dsa
- When prompted for a passphrase, you can just leave blank.
- Now go into the new file generated id_dsa.pub and copy the contents.
- Log into the remote host.
- Go to the directory /root/.ssh/.
- Edit or create the file authorized_keys. You will paste the contents from id_dsa.pub that you copied from the local machine in there.
That is all there is to it. When you ssh from the local machine to the remote machine now, it will go straight into it without prompting you for a password.
Tuesday, October 11, 2011
Installing Qt to Use with Visual Studio
Whenever I get a new computer or I install a new version of either Qt or Visual Studio, I have to stumble to get the 2 to play well together. They have the process documented kind of for the open source version. I wanted to put the steps that I use here.
The first thing that you will want to do is install the Qt sdk. It can usually be found at http://qt.nokia.com/downloads. You can do the quick install or choose to do a custom install. That is up to you for what you may want to include on the install.
Next, you will want to install the Qt Visual Studio Add-in. It is also usually found at http://qt.nokia.com/downloads. You can follow the default settings.
Setting Up the Environment Variable
Once these are installed, you will need to set the PATH environment variable. In order to do this, do the following;
The first thing that you will want to do is install the Qt sdk. It can usually be found at http://qt.nokia.com/downloads. You can do the quick install or choose to do a custom install. That is up to you for what you may want to include on the install.
Next, you will want to install the Qt Visual Studio Add-in. It is also usually found at http://qt.nokia.com/downloads. You can follow the default settings.
Setting Up the Environment Variable
Once these are installed, you will need to set the PATH environment variable. In order to do this, do the following;
- Click on the Start Menu
- Right Click on Computer
- Click on Properties
- You will now need to determine where the product was installed in order to determine what value to add to the Path. You will want to find the bin directory for the source. For instance, when I installed 4.7.4, the program was installed in C:\QtSDK\QtSources\4.7.4\bin. This would be the value I would add to the Path variable. Be careful with your formatting when adding the value.
Building the Qt Library
We will want to build the Qt Library now. This is where it gets a little tricky especially if you have multiple versions of Visual Studio installed or other C++ compilers.
In order to build, you will want to do the following:
- Open a command line prompt, but with the environment variables set for Visual Studio. You can do this from the tools folder in VS. I will use VS 2010 as an example.
- On the command line, navigate to the directory where Qt was installed. For me, it would be C:\QtSDK\QtSources\4.7.4\.
- Now, on the command line you will want to run the configure command. It will look like the following:
configure -platform win32-msvc2010
Notice where I have win32-msvc2010. This will be different for you depending on which version of Visual Studio you have on your machine or want to use. - Now run the following:
nmake
Qt has now been build
Configure Qt in Visual Studio
Once we have these steps done, we will need to configure Qt in VS. In order to do this, do the following.
- Make sure the Qt Versions Tab is Selected and Click the Add Button
- Add a version name and select the path to the version. For me the path would be C:\QtSDK\QtSources\4.7.4
You should now be able to create a Qt project inside of Visual Studio with no issues.
Wednesday, October 5, 2011
Free DNS Server
Google provides free public DNS servers to use. This is a great service to have for backup in case your primary DNS is having issues. The ip addresses for their servers are the following:
8.8.8.8
8.8.4.4
Here is a link to their service if you need an explanation:
http://code.google.com/speed/public-dns/
8.8.8.8
8.8.4.4
Here is a link to their service if you need an explanation:
http://code.google.com/speed/public-dns/
Thursday, September 29, 2011
Adding a Custom Favicon to a Site on Google Sites
Because of my family and friends, I have had to use the Google Sites CMS. It is not bad. It is limited, but it will get the job done for a basic static website. One of the things I wanted to be able to do was change the favicon on the website. The following is what their default is.
In order to change it, I go to my trusty icon maker and create a favicon.ico file. It has to be named that exact name. After I have my file, I have to get it up for the website. In order to do this, I do the following:
Click on More More Actions -> Manage Site in the top left
Then, on the right, choose Attachments
Then Click the Upload Button. The following box will appear.
Make sure that the attachment is being uploaded to / (top level).
Select the favicon.ico file and upload it.
Once that is done, your website will now show the favicon.
Favicon Tool
many times when I am making a website, I want to make a favicon.ico. I have founf a free tool that allows you to upload a picture and it will download a favicon file. The link to it is the following:
It is quick and easy to use. It makes my life easy!
Wednesday, August 31, 2011
Facebook Getting Worried About Anonymous It Seems
I just read an article that was talking about how Facebook is paying people for bugs they may find with their site. I think the bounty is low for what people mat be reporting to them according to the article. I think this is a good idea and good business practice, but it may also drive those that find these bugs or vulnerabilities to a competitor or somebody who is trying to be malicious such as Anonymous.
If you have not seen the warning from Anonymous here is a link to it.
If you have not seen the warning from Anonymous here is a link to it.
Tuesday, August 30, 2011
Using the jQuery DatePicker
I had a need to use a good date picker in a web page and I went with the jQuery library in order to have a set of tools that would be robust for GUI creation. It was fairly easy to implement.
The first hing I did was include the files that I would need from jQuery. The following did that for me:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css" type="text/css" media="all" />
I placed these lines in the header of my html file.
I then created a text element for data entry. this is where the date is going to go:
<INPUT TYPE=TEXT id="thedate">
I placed this line in the body of the html file. Now, I added the code in order to display the date picker in the text element I had created. I did this by creating a JavaScript function and putting it in the header of my html file. The code looked like what is below:
<script>
$(function()
{
$("#thedate").datepicker({dateFormat: 'yy-mm-dd'});
})
</script>
The first hing I did was include the files that I would need from jQuery. The following did that for me:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/jquery-ui.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.15/themes/base/jquery-ui.css" type="text/css" media="all" />
I placed these lines in the header of my html file.
I then created a text element for data entry. this is where the date is going to go:
<INPUT TYPE=TEXT id="thedate">
I placed this line in the body of the html file. Now, I added the code in order to display the date picker in the text element I had created. I did this by creating a JavaScript function and putting it in the header of my html file. The code looked like what is below:
<script>
$(function()
{
$("#thedate").datepicker({dateFormat: 'yy-mm-dd'});
})
</script>
The one thing you will see is that I have 'yy-mm-dd'. I have this in the constructor of the datepicker in order to format the date correctly for what I am expecting. You can enter all kinds of parameters in here at the creation of the datepicker. A link to the jQuery datepicker site is here.
Monday, August 22, 2011
SugarCRM - Turn Off Grouping in Tabs for 6.2
I wanted to turn off the nice functionality that was added to 6.2 because of the familiarity that users already had to the old format. In order to do this, it was fairly easy. A line just has to be added to the theme definition file. In this post, I created a new theme. In order to turn off the grouping, I added the following line after the name line. So, after 'name' => "Theme1",
I added:
'group_tabs' => false,
That is it. Now you will not have grouped tabs.
I added:
'group_tabs' => false,
That is it. Now you will not have grouped tabs.
SugarCRM - Removing SiteMap and Global Search
I am trying to simplify the SugarCRM interface for use by our internal staff an I wanted to remove the features not needed for them. 2 of the features I wanted to remove were the Site Map drop-down and the Search which are both in the top-right corner.
In order to do this, I created a new theme. I did this making a copy of the default theme. I made a new directory called custom/themes/NewTheme/. In here I copied all of the files and directories from themes/Sugar5/. This included the following:
css/
images/
js/
layout_utils.php
themedefs.php
tpls/
Now, I edited themedefs.php in order to reflect the name of my new theme. In order to do this, just change the line 'name' => "Classic". I changed my theme to be named Theme1. So my new line looked like the following:
'name' => "Theme1",
In order to now see this theme, you will want to choose it in the Admin. In order to do this, click on Administrator->Themes. Choose the new theme Theme1. Then, click Save.
You will now see the changes you make to the new theme that you created. In order to get rid of the 2 elements from above, we would need to edit custom/themes/TEJAS1/tpls/_headerSearch.tpl. In this file, remove the following code:
<div id="search">
<form name='UnifiedSearch' onsubmit='return SUGAR.unifiedSearchAdvanced.checkUsaAdvanced()'>
<input type="hidden" name="action" value="UnifiedSearch">
<input type="hidden" name="module" value="Home">
<input type="hidden" name="search_form" value="false">
<input type="hidden" name="advanced" value="false">
<img id="unified_search_advanced_img" src="{sugar_getimagepath file='searchMore.gif'}" border="0" alt="{$APP.LBL_SEARCH}">
<input type="text" name="query_string" id="query_string" size="20" value="{$SEARCH}">
<input type="submit" class="button" value="{$APP.LBL_SEARCH}">
</form><br />
<div id="unified_search_advanced_div"> </div>
</div>
<div id="sitemapLink">
<span id="sitemapLinkSpan">
{$APP.LBL_SITEMAP}
<img src="{sugar_getimagepath file='MoreDetail.png'}">
</span>
</div>
In order to do this, I created a new theme. I did this making a copy of the default theme. I made a new directory called custom/themes/NewTheme/. In here I copied all of the files and directories from themes/Sugar5/. This included the following:
css/
images/
js/
layout_utils.php
themedefs.php
tpls/
Now, I edited themedefs.php in order to reflect the name of my new theme. In order to do this, just change the line 'name' => "Classic". I changed my theme to be named Theme1. So my new line looked like the following:
'name' => "Theme1",
In order to now see this theme, you will want to choose it in the Admin. In order to do this, click on Administrator->Themes. Choose the new theme Theme1. Then, click Save.
You will now see the changes you make to the new theme that you created. In order to get rid of the 2 elements from above, we would need to edit custom/themes/TEJAS1/tpls/_headerSearch.tpl. In this file, remove the following code:
You may also want to add some other code in here in the same place for spacing. The 2 elements should now be gone.
SugarCRM - Removing the Links of Employees, Supposrt, Help, and About
I am trying to simplify the SugarCRM interface for use by our internal staff an I wanted to remove the links in the top-right corner since they will not have a need for them. The links I would be removing would be "Employees", "Support", "Help", and "About". In order to do this, it was fairly easy. I just added a file into custom/include/ named globalControlLinks.php. I put the following in it:
<?php
unset($global_control_links['employees'] );
unset($global_control_links['training'] ); //removes support link
unset($global_control_links['help'] );
unset($global_control_links['about'] );
?>
<?php
unset($global_control_links['employees'] );
unset($global_control_links['training'] ); //removes support link
unset($global_control_links['help'] );
unset($global_control_links['about'] );
?>
Notice the second unset. This is what you have to put in there in order to remove the "Support" link. Once I did this, the links were gone.
Wednesday, August 10, 2011
SugarCRM - Removing Buttons from a Subpanel
I needed to remove the buttons from a couple of subpanels in SugarCRM. The process to do this was little convoluted but I finally figured out all of the pieces I needed to modify. Here is the process for removing the buttons on a subpanel for my Contacts module in the Accounts module.
The first thing that I had to do was copy the default subpanel layout file over to the custom directory so I could modify it. Since I was modifying the Contacts subpanel, I copied the modules/Contacts/metadata/subpanels/default.php file over to custom/modules/Contacts/metadata/subpanels/default.php. I then renamed the file to ForAccounts.php. I did this so i would not be overwriting the default subpanel layout. The reason I moved it to the custom directory was to make sure that this was upgrade safe.
Now, I opened ForAccounts.php and changed the part of it that defined the buttons. In mine, I had the following:
'top_buttons' =>
array (
0 =>
array (
'widget_class' => 'SubPanelTopCreateButton',
),
1 =>
array (
'widget_class' => 'SubPanelTopSelectButton',
'popup_module' => 'People',
),
),
I changed this to
'top_buttons' =>
array (),
'top_buttons' => array ( 0 => array ( 'widget_class' => 'SubPanelTopButtonQuickCreate', ), 1 => array ( 'widget_class' => 'SubPanelTopSelectButton', 'mode' => 'MultiSelect', ), ),
The first thing that I had to do was copy the default subpanel layout file over to the custom directory so I could modify it. Since I was modifying the Contacts subpanel, I copied the modules/Contacts/metadata/subpanels/default.php file over to custom/modules/Contacts/metadata/subpanels/default.php. I then renamed the file to ForAccounts.php. I did this so i would not be overwriting the default subpanel layout. The reason I moved it to the custom directory was to make sure that this was upgrade safe.
Now, I opened ForAccounts.php and changed the part of it that defined the buttons. In mine, I had the following:
'top_buttons' =>
array (
0 =>
array (
'widget_class' => 'SubPanelTopCreateButton',
),
1 =>
array (
'widget_class' => 'SubPanelTopSelectButton',
'popup_module' => 'People',
),
),
I changed this to
'top_buttons' =>
array (),
I then saved my changes.
Now that I have a new definition, I have to let the subpanel know to use it. In order to do this, you have to edit the subpanel file in the module. For the accounts module, this is located in custom/Extension/modules/Accounts/Ext/Layoutdefs/. Look at the files and find the one that defines your subpanel. For me, it was contacts_accounts_Accounts.php.
In this file you will need to edit the subpanel_name field. You will need to change the value of it to what you called your new file above. For me in this example, I would change it to ForAccounts.
'subpanel_name' => 'ForAccounts',
Also, you will need to take out the code that defines the buttons in this file. So, make sure you delete the top_buttons field.
I then did a Quick Repair and Rebuild from the Repair link in the Admin module.
This got rid of the buttons at the top of the subpanel.
Tuesday, August 9, 2011
SFTP for Windows
For the longest time I have been using WinSCP for my SFTP client on Windows. it has been sufficient for the needs that I had. Recently, though, I had a need to move some larger files off of a Windows box. Now, I had a 100Mbps connection, but using WinSCP, I was only getting about 150kBps. Since I had files that were ~15GB and I needed to download a file a day, this was not going to work. I found an SFTP client that performas much better. It is called Tunnelier. I am getting speeds of about 675kBps with it. It is free for personal use. Here is a link to the product:
I am still getting used to the interface and all of the windows it opens up. I am going to play with the scripting client and see what I can do with it.
Thursday, July 28, 2011
SugarCRM - Accessing Database
I wanted to do a custom query in SugarCRM and I wanted to use the database connection that was already there so I would not have to create a custom connection in case I switched databases or something. In order to do this, it was really easy. All I had to do was add the following line of code:
global $db;
This gave me access to the db class. Below is an example of using it:
global $db;
$query = "SELECT now() AS thetime;";
$res = $db->query($query);
$row = $db->fetchByAssoc($res);
$TheTime = $row['thetime'];
$GLOBALS['log']->debug("time: $TheTime");
The code above will put a timestamp in the log when accessed.
global $db;
This gave me access to the db class. Below is an example of using it:
global $db;
$query = "SELECT now() AS thetime;";
$res = $db->query($query);
$row = $db->fetchByAssoc($res);
$TheTime = $row['thetime'];
$GLOBALS['log']->debug("time: $TheTime");
The code above will put a timestamp in the log when accessed.
SugarCRM - Adding a Logic Hook for the Accounts Module
I am keeping track of some information for accounts in a separate database outside of the CRM. When account information is changed, such as who it is assigned to, I need to be notified so I can capture those changes and make them to the other database. In order to do that, I had to add a logic hook. This entry will explain how I did that.
The first thing I did was create a file that defines an entry point into the hook for the Accounts module. I did this in custom/modules/Accounts/ in a file called logic_hooks.php. The code I used to define the hook is the following:
<?PHP
$hook_version =1;
$hook_array = Array();
$hook_array['after_save'] = Array();
$hook_array['after_save'][] = Array(1, 'TestHook', 'custom/modules/Accounts/AccountsLogicHook.php', 'AccountsLogicHook', 'onTestHookAfterSave');
?>
The last line defines the hook. Notice the parameter 1. This defines an order in case you have multiple hooks defined. The text TestHook is a label that you can define as some string to identify the hook. The next parameter custom/modules/Accounts/AccountsLogicHook.php lists the file that the class is located where your method is in. In other words, it is the file where the code that you want to execute is located. The next parameter AccountsLogicHook defines the class that the method is in. The last parameter onTestHookAfterSave is the name of the method. That is all I need in this file.
In the last line I also define the action for which I would like the hook to fire. The action I have defined is after_save. There is a list of available hooks in the documentation, but here is a sample of them:
after_ui_frame
after_ui_footer
after_round_trip
before_delete
after_delete
before_save
after_save
Now, the second file I created was custom/modules/Accounts and it is also in custom/modules/Accounts. Notice how this matches up with the third parameter up above. In the file, i put the following code:
<?PHP
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
class AccountsLogicHook
{
function onTestHookAfterSave(&$bean, $event, $arguments)
{
$GLOBALS['log']->fatal("The account hook worked!");
}
}
?>
Notice how I named a class as specified as the 4th parameter of my array above. I also named my method as specified as the 5th parameter of my array above. This method will put an entry in the log file when fired.
Wednesday, July 27, 2011
SugarCRM - Adding Logging into sugarcrm.log
If you would like to use the SugarCRM log in order to help you debug an issue you may be having with some code, it is fairly easy to do. All you have to do is add the following line of code:
$GLOBALS['log']->debug("Debug Message");
In order to view this message, you must make sure that you have set this message up correctly. First, notice in the call above, I have the debug piece in the call. This refers to the actual level of the call. In order to view this message in the log, you will need to make sure that the setting in the admin is set to be at this setting or above to view these messages. You may choose to change the level of the message to any of the levels listed below. Just be careful with case.
If you go to Admin->System Settings->Log Level, there is a drop-down box of the levels that you can be at. They are listed in order of precedence. If you have a level at a higher level, it will display messages for those of the lower level. Here is the list:
Debug
Info
Warn
Deprecated
Error
Fatal
Security
Off
So, if you have Error chosen, it will show messages marked as Error or Security.
Where I have "Debug Message", you may put any message that you would like displayed in your log.
In order to view the log, you can view it from the link in the admin right below the drop-down mentioned above or you can use an editor.
$GLOBALS['log']->debug("Debug Message");
In order to view this message, you must make sure that you have set this message up correctly. First, notice in the call above, I have the debug piece in the call. This refers to the actual level of the call. In order to view this message in the log, you will need to make sure that the setting in the admin is set to be at this setting or above to view these messages. You may choose to change the level of the message to any of the levels listed below. Just be careful with case.
If you go to Admin->System Settings->Log Level, there is a drop-down box of the levels that you can be at. They are listed in order of precedence. If you have a level at a higher level, it will display messages for those of the lower level. Here is the list:
Debug
Info
Warn
Deprecated
Error
Fatal
Security
Off
So, if you have Error chosen, it will show messages marked as Error or Security.
Where I have "Debug Message", you may put any message that you would like displayed in your log.
In order to view the log, you can view it from the link in the admin right below the drop-down mentioned above or you can use an editor.
Monday, July 25, 2011
SugarCRM - Hiding Subpanels with Code
I was using the Display Module Tabs and Subpanels feature of SugarCRM in order to hide the modules that we were not using currently. The issue i ran into was that not all of the subpanels were being hidden on the modules even though I had set them to be hidden.
For my example, I was trying to hide the subpanels for Activities and History in the Accounts module. In order to do this, I created a file in custom/Extension/modules/Accounts/Ext/Layoutdefs/ called mycustom.php and I put the following in there:
<?PHP
unset($layout_defs['Accounts']['subpanel_setup']['activities']);
unset($layout_defs['Accounts']['subpanel_setup']['history']);
?>
I then did a Quick Repair and Rebuild from the Repair link in the Admin module. This hid those subpanels and should be upgrade safe.
SugarCRM - Adding a Custom View Using the MVC Model
I had been trying to find a good example of adding a custom view to an existing module in SugarCRM using the MVC model, but was unsuccessful. I did find some examples though that did tasks that were similar and i was able to put together this example of adding the custom view.
The tasks that I will do in order to accomplish this are the following:
1. Add a new item to the menu bar for calling the new view
2. Add a controller for the module that will define the new action
3. Create the new view
For my example I will be adding a new view called see1 that has a label of "See Me" in the menu to the Accounts module.
1. Add New Item to Menu Bar
In order to do this, you will need to make a new file called menu.ext.php in custom/Extension/modules/Accounts/Ext/Menus/. If the directory does exist, go ahead and make it. In menu.ext.php you will need the following code:
<?PHP
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
if(ACLController::checkAccess('Accounts', 'edit', true)) $module_menu[]=Array(
"index.php?module=Accounts&action=See1",
"See Me","Accounts");
?>
The label of the link is defined above as See Me. Also, I have defined the action as See1. This is important to keep track of for the controller.
This file will now Add the link See Me to the other links for the Accounts module. So, for me, I now have 4 Actions listed: Create Account, View Accounts, Import Accounts, and See Me.
2. Add a Controller
Now that we have a link calling a new action, we need to define what the new action will do. In order to do this, we need to create a new file that maps the action. The new file will be called controller.php. and it will reside in custom/modules/Accounts/. The contents of the file will be the folloiwng:
<?PHP
require_once('include/MVC/Controller/SugarController.php');
class AccountsController extends SugarController {
function action_See1() {
$this->view = "lookatit";
}
}
?>
Here are a couple of notes about the file above. The naming convention is case sensitive. Also, notice how the action is defined as a function with the prefix "action_". Lastly, the name of the view that will be called is defined in this as lookatit. This is important to remember for he next step.
3. Create a New View File
The last step in getting the new view to work is creating the new view that you would like to see. In order to do this, we will need to create a new file in custom/modules/Accounts/views/. If the directory does not exist, go ahead and create it. The new file to put in the directory will be called view.lookatit.php. The naming convention is important in that you have view preface it and the view name, "lookatit" for me, from the controller as the name. In the file you could put the following:
<?PHP
require_once('include/MVC/View/SugarView.php');
class AccountsViewLookAtIt extends SugarView {
public function AccountsViewLookAtIt() {
parent::SugarView();
}
public function display() {
echo "Here!\n";
}
}
?>
The contents of this file will contain whatever you would like your new view to have. This example just shows the text "Here!", but it is in the SugarCRM frame.
So, this gets us to the point of having a custom view inside of the MVC framework of SugarCRM.
Subscribe to:
Posts (Atom)