Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-negotiation-strategy-effective-implementation-cots-software
Packt
05 Feb 2010
8 min read
Save for later

Negotiation Strategy for Effective Implementation of COTS Software

Packt
05 Feb 2010
8 min read
Having effective executive sponsorship is a key success factor for any business solution implementation. There are countless books and presentations that have communicated this best practice to the marketplace. Executive sponsorship may guarantee financial support but it does not guarantee organizational acceptance and adoption. For example, Panorama Consulting conducted a study of 2008 Enterprise resource planning (ERP) implementations from over one thousand organizations across the globe. The study focused on the top ERP challenges. Respondents indicated that lack of employee adoption as the biggest challenge (33%). Surprisingly, not a single respondent identified lack of executive support as the biggest problem. Trickle down acceptance falls short A key assumption made on several packaged software implementations is that if the executive management selects Commercial Off The Shelf (COTS) software, then the organization would adopt the executive's intentions. When executive management selects packaged software, they are making the following statement: A custom software solution is not strategic for the organization. It is interesting to note that the above statement is not publicly reiterated throughout the life of the implementation project. It's like a little secret that is implied but hardly repeated. Unfortunately, the key business process owners and other stakeholders do not always respond to "trickle down" acceptance. Their expectation is based on their past software experience, which is usually getting what they want without any questions asked. Packaged software makes for an expensive custom solution. If the project team does not reset existing business software expectations, then it will be extremely difficult to be successful. If the project team makes no software changes and use packaged software as delivered then end user adoption and satisfaction will be harder to develop. If the project team focuses on building a custom solution then the Total Cost of Ownership (TCO) will be significant and will result in less executive satisfaction due to the increased cost. Successful COTS software implementations are those that are able to balance (negotiate) tradeoffs that result in minimizing TCO and maximizing organizational acceptance. The following section will discuss the key areas that the project team should address as part of their negotiation strategy. Developing an effective negotiation strategy An effective negotiation strategy for packaged software implementations is where all parties are aligned in supporting the success of the implementation. It is also importantfor the project team to perform certain activities to promote alignment and adoption. The first step in developing an effective negotiation strategy is to establish realistic expectations to close the gap between custom software and packaged software. Paradigm shift in business software expectations One of the key mindsets that the project team have to make with the stakeholders and end users are expectations of business software. Typically, stakeholders and end users see business software as a simple tool that can easily be adapted to support their activities. It is rare for stakeholders and end users to understand the complete ramifications of their requests. There are times when stakeholders and end users do not care to know what efforts are required to make the business software do exactly what they want. Regardless of the underlying drivers, the project team must make the effort to educate and influence stakeholders and end users to develop areas of compromise. Case Study I was the functional consulting lead for a packaged software application to replace a customer's legacy time reporting system. The customer's process consisted of electronic spreadsheets coupled together with a data load process to a staging table for payroll processing. When I started working with the customer to define their business requirements, it was apparent that there was a difference between executive and business stakeholder expectations. The customer insisted on having the exact functionality that they had in their existing systems. I knew that no matter how good the developers were, we would not be able to cost-effectively build the existing flexibility into the packaged software. It would totally invalidate the justification for going with a packaged software solution in the first place. The customer was used to getting exactly what they wanted from software to the point where software replaced the need for training (i.e., dummy-proofing). I did an initial gap analysis and identified over forty (40) gaps that required changes to the packaged software. I came to the realization that if I proceeded with a traditional approach to gathering requirements that: (a) I would spend a lot of wasted effort gathering non-value-added business requirements and (b) the fit/gap session would be much longer than anticipated. It was a no-win situation. The best approach was to reset software expectations with the customer up-front. I met with the customer to discuss the reasons for selecting packaged software and the inherent advantages and disadvantages with packaged software. This was not a one-time discussion and required several additional discussions. In the end, the customer's expectations adapted, which enabled us to accelerate our fit/gap session. We still identified ten gaps. Of the ten gaps, we negotiated to have only five addressed via a software change and the other five gaps were handled manually due to the frequency of occurrence. Our negotiations resulted in an 87% reduction from the initial estimate and were only made possible by establishing a suitable environment for effective negotiating. If either party has unrealistic expectations then effective negotiations would have been extremely difficult. Paradigm shift in organizational acceptance The second paradigm shift that the project team has to make is in how to gain organizational acceptance. This area is addressed in organizational change management. Organizational Change Management is good at defining the tactical steps that you need to perform in preparing the organization for a new business solution. However, a more aggressive approach needs to be taken. The entire project team needs to sell the solution to the organization. I'm talking about a concerted effort—no soft selling here. The project team needs to have real influence with the stakeholders and end users. The project team needs to lead discussions with stakeholders and key end users; negotiating a business solution that balances their needs (not wants) with the strategy of using packaged software. The project team needs to persuade their customers that they have the customer's best interests at heart and will produce a competent business solution. Understand when and where to negotiate Negotiating on business requirements is a certainty that must be planned for by the project team. The majority of projects do not have a proactive strategy in place to negotiate with stakeholders on business requirements that are not satisfied by the delivered packaged software. Many projects take a reactive approach to negotiating business requirements. This approach typically results in confusion, analysis paralysis, and decisions that undermine the objectives of selecting packaged business software. Following are the key points that the project team needs to address in understanding potential areas for negotiation: Identify areas within the packaged software where software changes are typically made by customers. With the correct implementation partner, the project team may have the opportunity to leverage their software change library to streamline the modification efforts. With the correct packaged software provider, you may have the opportunity to partner together and share the development effort. Identify areas within the packaged software where software changes will have minimal Total Cost of Ownership impact. For example, making a software changes to generate an exception report has less of an impact than building a new application page or process. Determine where the business software provider provides the most support for software changes within their application and lead with these options in the negotiations. For example, reporting is an area that most packaged software providers anticipate their customers modifying, and provide tools and templates for streamlined development and upgrades in this area. Identify areas within the packaged software where software changes will have an adverse impact to the Total Cost of Ownership. For example, software modifications to compiled executables can have several downstream impacts to other components within the packaged software. These software changes can not only negatively impact the Total Cost of Ownership but can also result in unstable business software, and invalidate software support and quality agreements. It is also important for the project team to understand the boundaries of the technical constraints inherent with the packaged software. Determine what to challenge and what to accept regarding business requirements not supported by the packaged software. In general, the project team should focus on maximizing enhancements and minimizing customizations. In the case where customizations must be addressed for project success, implement the customizations with the least impact to the Total Cost of Ownership. As the project team engages the key stakeholders and end users, do not lead with the functional areas that the team plans to address via software changes. Allow the stakeholders and end users to justify the reasons for negotiating and building software changes. What I learned from these software negotiations is that every party needs to perceive that they have won something. In theory, one can look at this as an inefficient process; however, it reflects human nature and a certain reality that the project team must address. The project team, should as well deal with these types of negotiations in a practical manner. Too often, I have witnessed project teams get stuck in theoretical absolutes that add no business value and slow down the project.
Read more
  • 0
  • 0
  • 4752

article-image-n-way-replication-oracle-11g-streams-part-2
Packt
05 Feb 2010
7 min read
Save for later

N-Way Replication in Oracle 11g Streams: Part 2

Packt
05 Feb 2010
7 min read
Streaming STRM2 to STRM1 Now the plan for setting up Streams for STRM2. It is the mirror image of what we have done above, except for the test part. On STRM2, log in as STRM_ADMIN. -- ADD THE QUEUE, a good queue name is STREAMS_CAPTURE_Q -- ADD THE CAPTURE RULE -- ADD THE PROPAGATION RULE -- INSTANTIATE TABLE ACROSS DBLINK -- DBLINK TO DESTINATION is STRM1.US.APGTECH.COM -- SOURCE is STRM2.US.APGTECH.COM On STRM1 log in as STRM_ADMIN. -- ADD THE QUEUE: A good queue name is STREAMS_APPLY_Q -- ADD THE APPLY RULE Start everything up and test the Stream on STRM2. Then check to see if the record is STREAM'ed to STRM1. -- On STRM2 log in as STRM_ADMIN -- ADD THE QUEUE :A good queue name is STREAMS_CAPTURE_Q -- STRM_ADMIN@STRM2.US.APGTECH.COM>BEGINDBMS_STREAMS_ADM.SET_UP_QUEUE(queue_table => '"STREAMS_CAPTURE_QT"',queue_name => '"STREAMS_CAPTURE_Q"',queue_user => '"STRM_ADMIN"');END;/commit;-- ADD THE CAPTURE RULE-- STRM_ADMIN@STRM2.US.APGTECH.COM>BEGINDBMS_STREAMS_ADM.ADD_TABLE_RULES(table_name => '"LEARNING.EMPLOYEES"',streams_type => 'capture',streams_name => '"STREAMS_CAPTURE"',queue_name => '"STRM_ADMIN"."STREAMS_CAPTURE_Q"',include_dml => true,include_ddl => true,include_tagged_lcr => false,inclusion_rule => true);END;/commit;-- ADD THE PROPAGATION RULE-- STRM_ADMIN@STRM2.US.APGTECH.COM>BEGINDBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(table_name => '"LEARNING.EMPLOYEES"',streams_name => '"STREAMS_PROPAGATION"',source_queue_name =>'"STRM_ADMIN"."STREAMS_CAPTURE_Q"',destination_queue_name =>'"STRM_ADMIN"."STREAMS_APPLY_Q"@STRM1.US.APGTECH.COM',include_dml => true,include_ddl => true,source_database => 'STRM2.US.APGTECH.COM',inclusion_rule => true);END;/COMMIT; Because the table was instantiated from STRM1 already, you can skip this step. -- INSTANTIATE TABLE ACROSS DBLINK-- STRM_ADMIN@STRM2.US.APGTECH.COM>DECLAREiscn NUMBER; -- Variable to hold instantiation SCN valueBEGINiscn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@STRM1.US.APGTECH.COM(source_object_name => 'LEARNING.EMPLOYEES',source_database_name => 'STRM1.US.APGTECH.COM',instantiation_scn => iscn);END;/COMMIT; -- On STRM1, log in as STRM_ADMIN. -- ADD THE QUEUE, a good queue name is STREAMS_APPLY_Q-- STRM_ADMIN@STRM1.US.APGTECH.COM>BEGINDBMS_STREAMS_ADM.SET_UP_QUEUE(queue_table => '"STREAMS_APPLY_QT"',queue_name => '"STREAMS_APPLY_Q"',queue_user => '"STRM_ADMIN"');END;/COMMIT;-- ADD THE APPLY RULE-- STRM_ADMIN@STRM1.US.APGTECH.COM>BEGINDBMS_STREAMS_ADM.ADD_TABLE_RULES(table_name => '"LEARNING.EMPLOYEES"',streams_type => 'apply',streams_name => '"STREAMS_APPLY"',queue_name => '"STRM_ADMIN"."STREAMS_APPLY_Q"',include_dml => true,include_ddl => true,include_tagged_lcr => false,inclusion_rule => true);END;/commit; Start everything up and Test. -- STRM_ADMIN@STRM1.US.APGTECH.COM>BEGINDBMS_APPLY_ADM.SET_PARAMETER(apply_name => 'STREAMS_APPLY',parameter => 'disable_on_error',value => 'n');END;/COMMIT;-- STRM_ADMIN@STRM1.US.APGTECH.COM>DECLAREv_started number;BEGINSELECT DECODE(status, 'ENABLED', 1, 0) INTO v_startedFROM DBA_APPLY where apply_name = 'STREAMS_APPLY';if (v_started = 0) thenDBMS_APPLY_ADM.START_APPLY(apply_name => '"STREAMS_APPLY"');end if;END;/COMMIT;-- STRM_ADMIN@STRM2.US.APGTECH.COM>DECLAREv_started number;BEGINSELECT DECODE(status, 'ENABLED', 1, 0) INTO v_startedFROM DBA_CAPTURE where CAPTURE_NAME = 'STREAMS_CAPTURE';if (v_started = 0) thenDBMS_CAPTURE_ADM.START_CAPTURE(capture_name => '"STREAMS_CAPTURE"');end if;END;/ Then on STRM2: -- STRM_ADMIN@STRM2.US.APGTECH.COM>ACCEPT fname PROMPT 'Enter Your Mom's First Name:'ACCEPT lname PROMPT 'Enter Your Mom's Last Name:'Insert into LEARNING.EMPLOYEES (EMPLOYEE_ID, FIRST_NAME, LAST_NAME,TIME) Values (5, '&fname', '&lname', NULL);dbms_lock.sleep(10); --give it time to replicate Then on STRM1, search for the record. -- STRM_ADMIN@STRM1.US.APGTECH.COM>Select * from LEARNING.EMPLOYEES; We now have N-way replication. But wait, what about conflict resolution?Good catch; all of this was just to set up N-way replication. In this case, it is a 2-way replication. It will work the majority of the time; that is until there is conflict. Conflict resolution needs to be set up and in this example the supplied/built-in conflict resolution handler MAXIMUM will be used. Now, let us cause some CONFLICT! Then we will be good people and create the conflict resolution and ask for world peace while we are at it! Conflict resolution Conflict between User 1 and User 2 has happened. Unbeknown to both of them, they have both inserted the exact same row of data to the same table, at roughly the same time. User 1's insert is to the STRM1 database. User 2's insert is to the STRM2 database. Normally the transaction that arrives second will raise an error. It is most likely that the error will be some sort of primary key violation and that the transaction will fail. We do not want that to happen. We want the transaction that arrives last to "win" and be committed to the database. At this point, you may be wondering "How do I choose which conflict resolution to use?" Well, you do not get to choose, the Business Community that you support will determine the rules most of the time. They will tell you how they want conflict resolution handled. Your responsibility is to know what can be solved with built-in conflict resolutions and when you will need to create custom conflict resolution. Going back to User 1 and User 2. In this particular case, User 2's insert arrives later than User 1's insert. Now the conflict resolution is added using the DBMS_APPLY_ADM package, specifically the procedure DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_ HANDLER which instructs the APPLY process on how to handle the conflict. Scripts_5_1_CR.sql shows the conflict resolution used to resolve the conflict between User 1 and User 2. Since it is part of the APPLY process, this script is run by the Streams Administrator. In our case, that would be STRM_ADMIN. This type of conflict can occur on either STRM1 or STRM2 database, so the script will be run on both databases. The numbers to the left are there for reference reasons. They are not in the provided code. -- Scripts_5_1_CR.sql1. DECLARE2. cols DBMS_UTILITY.NAME_ARRAY;3. BEGIN4. cols(0) := 'employee_id';5. cols(1) := 'first_name';6. cols(2) := 'last_name';7. cols(3) := 'time';8. DBMS_APPLY_ADM.SET_UPDATE_CONFLICT_HANDLER(9. object_name => 'learning.employees',10. method_name => 'MAXIMUM',11. resolution_column => 'time',12. column_list => cols);13. END;14. /15. Commit; So what do these 15 magical lines do to resolve conflict?Let us break it down piece by piece logically first, and look at the specific syntax of the code. Oracle needs to know where to look when a conflict happens. In our example, that is the learning.employees table. Furthermore, Oracle needs more than just the table name. It needs to know what columns are involved. Line 9 informs Oracle of the table. Lines 1 -7 relate to the columns. Line 8 is the actual procedure name. What Oracle is supposed to do when this conflict happens, is answered by Line 10. Line 10 instructs Oracle to take the MAXIMUM of the resolution_column and use that to resolve the conflict. Since our resolution column is time, the last transaction to arrive is the "winner" and is applied.
Read more
  • 0
  • 0
  • 1641

article-image-n-way-replication-oracle-11g-streams-part-1
Packt
05 Feb 2010
4 min read
Save for later

N-Way Replication in Oracle 11g Streams: Part 1

Packt
05 Feb 2010
4 min read
N-way replication refers to a Streams environment where there are multiple sources. In this article, we will still use the STRM1 and STRM2 databases but with a little twist; making both databases the source. By making both STRM1 and STRM2 sources, we need to first consider a couple of unique situations and do a little more pre-planning, specifically for N-Way replication. The concepts and techniques used to configure a 2-way replication can then be used to scale to N-way replication. We all need to crawl before we run, the better you crawl (understand) this article, the easier it will be to scale up to N-way replication. Pay close attention and learn the technique so that you can implement it well. We need to repeat this—Streams is not Failover. We need to repeat this—Streams is not Failover. No, that is not a typo. The authors are passionate about Streams and want to see you successfully implement it. To successfully implement Streams, you need to know not to step into the trap of using it for Failover. Both authors have done some work where Failover was the requirement. Streams is not a Failover solution. Failover is handled by Oracle Data Guard, NOT Oracle Streams. Streams is about distributing the data to multiple locations. On more than one occasion, Streams was used as a Failover technology because it can distribute data to multiple locations. Do not fall into the trap of using the wrong tool for the wrong job. Streams distributes (replicates) data. As such, there will always be some difference between the databases in a Streams environment. All replication technology has this problem. The only time where all of the databases are in sync is, when there is no activity and all replication has been applied to all target locations. If you need Failover, then use the proper tool. Oracle Data Guard is for Failover. It has the necessary processes to guarantee a different level of failover from a primary site to a secondary site, whereas Streams is a Replication tool that distributes data. Just remember the following, when there is a discussion of Replication and Failover that comes up: Streams distributes data, it is built for replication Data Guard is built for Failover Pre-planning for N-way replication When we set up N-way replication, we must consider the possibility of a collision of data. Since we have multiple sources of data, it is possible for the exact same data to be inputted on any or all of the sources at the exact same time. When this happens, it is a conflict. This example is just one type of conflict that can happen in N-way replication environments. The types of conflict that can occur are as follows: Update conflict: When transactions from different databases try to update the same row at nearly the same time. Delete conflict: When one transaction deletes a row and the next transaction tries to update or delete the row. Transactions originate from different databases. Unique conflict: When transactions from different databases violate a primary or unique constraint, the first transaction is accepted. The second transaction obtains the conflict. Foreign key conflict : This happens when a transaction from a Source tries to insert a child record before the parent record exists. The good news is that Oracle has provided built-in conflict resolution in Streams that solves the most common situations. The built-in solutions are as follows: OVERWRITE DISCARD MAXIMUM MINIMUM We will provide an example of conflict resolution after we build our N-way replication. In our case, we will use MAXIMUM. As part of the pre-planning for N-way replication, we highly suggest creating a simple table such as the Setup Table. Avoiding Conflict As conflict requires additional pre-planning and configuration, one begins to wonder, "Are there techniques so that we can configure N-way replication without the possibility of conflict?" The simple answer to the question is "Yes". The not-so simple answer is that there is some configuration magic that needs to be done and the devil is in the details. Limiting who and what can be updated is one method of avoiding conflict. Think of it this way— there is no conflict if we agree to who and what can update the specific data. User 1 can only update his specific data and no one else can do that. Similarly, user 2 can only update his specific data. So, user 1 and user 2 can never cause a conflict. Now this may be a little bit difficult depending on the application. This can be implemented with the use of offset sequences. One sequence produces only odd values, and another produces only even values. We could also use a combination of sequence and some unique characteristics of the database.
Read more
  • 0
  • 0
  • 2200

article-image-build-your-own-application-access-twitter-using-java-and-netbeans-part-1
Packt
05 Feb 2010
6 min read
Save for later

Build your own Application to access Twitter using Java and NetBeans: Part 1

Packt
05 Feb 2010
6 min read
Due to the fact that writing a Java app to control your Twitter account is quite a long process and requires several features, I intend to divide this article in several sections, so you can see in extreme detail all the bells and whistles involved in writing Java applications. Downloading and installing NetBeans for your developing platform To download NetBeans, open a web browser window and go to the NetBeans website. Then click on the Download button and select the All IDE download bundle. After downloading NetBeans, install it with the default options. Creating your SwingAndTweet project Open NetBeans and select File | New Project to open the New Project dialog. Now select Java from the Categories panel and Java Application from the Projects panel. Click on Next to continue. The New Java Application dialog will show up next. Type SwingAndTweet in the Project Name field, mark the Use Dedicated Folder for Storing Libraries option, deselect the Create Main Class box (we’ll deal with that later), make sure the Set as Main Project box is enabled and click on Next to continue: NetBeans will create the SwingAndTweet project and will show it under the Projects tab, in the NetBeans main window. Right click on the project’s name and select JFrame Form... in the pop-up menu: The New JFrame Form window will appear next. Type SwingAndTweetUI in the Class Name field, type swingandtweet in the Package field and click on Finish to continue: NetBeans will open the SwingAndTweetUI frame in the center panel of the main screen. Now you’re ready to assemble your Tweeter Java application! Now let me explain a little bit about what we did in the previous exercise: First, we created a new Java application called SwingAndTweet. Then we created a Swing JFrame component and we named it SwingAndTweetUI, because this is going to act as the foundation, where we’re going to put all the other Swing components required to interact with Twitter. Now I’m going to show you how to download and integrate the Twitter4J API to your SwingAndTweetJava application. Downloading and integrating the Twitter4J API into your NetBeans environment For us to be able to use the powerful classes and methods from the Twitter4J API, we need to tell NetBeans where to find them and integrate them into our Java applications. Open a web browser window, go to http://repo1.maven.org/maven2/net/homeip/yusuke/twitter4j/ and search for the latest twitter4j.2.X.X.jar file, or download the most recent version at the time of this writing from here:http://repo1.maven.org/maven2/net/homeip/yusuke/twitter4j/2.0.9/twitter4j-2.0.9.jar. Once you download it in your computer, go to NetBeans, right-click on the SwingAndTweet project and select Properties from the context menu. Once at the project properties screen, select the Libraries category under the Categories panel, click on the Add JAR/Folder... button at the middle-right part of the screen to open the Add JAR/Folder dialog, navigate to the directory where you downloaded the twitter4j-2.X.X.jar file and double click on it to add it to your project’s library path: Click on OK to close the Project Properties dialog and return to the NetBeans main screen. Ok, you have integrated the Twitter4J API to your SwingAndTweet application. Now, let’s see how to log into your Twitter account from our Java application... Logging into Twitter from Java and seeing your last Tweet In the following exercise, I’ll show you how easy it is to start communicating with Twitter from a Java application, thanks to the Twitter class from the Twitter4J API. You‘ll also learn how to check your last tweet through your Java application. Let’s see how to log into a Twitter account: Go to the Palette window and locate the JLabel component under the Swing Controls section; then drag and drop it into the TweetAndSwing JFrame component: Now drag a Button and a Text Editor, too. Once you have the three controls inside the SwingAndTweetUI JFrame control, arrange them as shown below: The next step is to change their names and captions, to make our application look more professional. Right click on the JLabel1 control, select Edit from the context menu, type My Last Tweet and hit Enter. Do the same procedure with the other two controls: erase the text in the jTextField1 control and type Login in the jButton1 control. Rearrange the jLabel1 and jTextField1 controls, and drag one of the ends of jTextField1 to increase its length all you can. Once done, your application will look like this: And now, let’s inject some life to our application! Double click on the JButton1 control to open your application’s code window. You’ll be inside a java method called jButton1ActionPerformed. This method will execute every time you click on the Login button, and this is where we’re going to put all the code for logging into your Twitter account. Delete the // TODO add your handling code here: line and type the following code inside the JButton1ActionPerformed method: Remember to replace username and password with your real Twitter username and password. If you look closely at the line numbers, you‘ll notice there are five error icons on lines 82, 84, 85,  88 and 89. That’s because we need to add some import lines at the beginning of your code, to indicate NetBeans where to find the Twitter and JOptionPane classes, and the TwitterException. Scroll up until you locate the package swingandtweet; line; then add the following lines: Now all the errors will disappear from your code. To see your Java application in action, press F6 or select Run  Run | Main Project from the NetBeans main menu. The Run Project window will pop up, asking you to select the main class for your project. The swingandtweet.SwingAndTweetUI class will already be selected, so just click on OK to continue. Your SwingAndTweetUI application window will appear next, showing the three controls you created. Click on the Login button and wait for the SwingAndTweet application to validate your Twitter username and password. If they’re correct, the following dialog will pop up: Click on OK to return to your SwingAndTweet application. Now you will see your last tweet on the textbox control: If you want to be really sure it’s working, go to your Twitter account and update your status through the Web interface; for example, type Testing my Java app. Then return to your SwingAndTweet application and click on the Login button again to see your last tweet. The textbox control will now reflect your latest tweet: As you can see, your SwingAndTweet Java application can now communicate with your Twitter account! Click on the X button to close the window and exit your SwingAndTweet application.
Read more
  • 0
  • 0
  • 6140

article-image-new-features-domino-designer-85
Packt
05 Feb 2010
7 min read
Save for later

New features in Domino Designer 8.5

Packt
05 Feb 2010
7 min read
There are many exciting changes and additions to Domino Designer 8.5. We will begin with the introduction of the Eclipse based integrated development environment. Domino Designer 8.5, which is also known as Domino Designer on Eclipse or DDE, takes advantage of Eclipse technology to deliver a more powerful developer environment. The look and feel is more consistent with Notes client version 8.x. The new UI will be examined at a high level. The next major feature addition that will be covered is XPages. XPages are a new type of design element being introduced in the 8.5 release that will revolutionize Domino Web Applications. XPages enable application developers to quickly and easily create rich Domino web applications with a Web 2.0 look and feel. Finally, we will review improvements to CSS support, enhancements to HTML generation, JavaScript controls, a new method related to ID Vault: ResetUserPassword, and changes to web services. Domino Designer on Eclipse Now in 8.5 the Domino Designer client is based on Eclipse, as the Notes client was in 8.x. Eclipse is an award-winning, open source platform for the construction of powerful software development tools and rich desktop applications. This architectural change allows the new designer client to become an open source pluggable environment. By allowing the use of plugins, objects can be built, re-used, and shared. Some of the differences in the new 8.5 Designer client can be seen when examining the processes associated with Domino Designer. It is useful to know how they relate to one another and what component each controls. Prior to release 8.5 designer clients, when you launched designer.exe, nlnotes.exe would be spawned. This is the process in which pre-8.5 Domino Designer ran. Now in the 8.5 Designer client, designer.exe loads and spawns nlnotes.exe. On faster machines, designer.exe shows up briefly, and may not be seen at all. Then the notes2.exe process spawns and designer.exe quits. notes2.exe is the Java process that corresponds to the Eclipse shell. Finally, nlnotes.exe spawns ntaskldr.exe after DDE opens. Some other things you may notice are that launch and exit take longer than in previous versions. This is due to the Eclipse startup and shutdown sequences. This can lead to problems on exit or launch. If you experience a problem with launch or exit, it may be due to one of the following issues. Due to the longer exit time, the user may have initiated launch before all prior processes had been killed, or the user may have initiated the launch sequence multiple times. It is also possible that, on prior exit, the client did not shut down all processes. With a few exceptions, the launch process will be able to compensate for these errors. However, if you still can't launch or exit the 8.5 designer client, you can try the following, manually. Kill the nlnotes.exe and notes2.exe processes with the task manager, or if the client still will not launch or exit, log off the system to completely kill all process threads. The new Eclipse-based GUI Now that the 8.5 Designer client is Eclipse based, there is a new UI. The default perspective in 8.5 is the Domino Designer perspective. There are other perspectives available in Domino Designer 8.5, each suited to a particular task. You can select a different perspective from the menu, select Window | Open Perspective | Other, as seen in the following screenshot: Not all perspectives have a corresponding layout in the UI. Perspectives can be customized to suit individual preferences. One way is by resizing the views and editors. You can resize views and editors in one of two ways. Click the Maximize/Restore button located in the title bar of the view or editor. Or, click and drag the border of a view or editor. Views and editors can also be hidden by clicking the view Close button. Use the menu pick Window | Show Eclipse Views to reopen closed views. You can use this menu pick to open any Eclipse view, including those from other perspectives. To return to the current perspective's default layout use the menu pick Window | Reset Perspective.... XPages For a while now it has been difficult to create elegant web applications for Notes/Domino. XPages are a new type of design element being introduced in the 8.5 release, that will allow application developers to quickly and easily create rich Domino web applications with a Web 2.0 look and feel. Applications built using XPages are supported for web use only, for the 8.5 release. To enhance the appearance and functionality for web use, existing applications can be extended to utilize XPages. The standard design elements must be included in the database for use in the Notes client and the application. If a new application is targeted for both Notes client and web users, then you can also include XPages for use on the Web. XPages are built on top of JSF, or Java Server Faces, technology. XPages also have built-in Ajax support, which allows application developers to take advantage of Ajax features such as type-ahead and partial page refresh. They are created in pure XML markup. When the application developer adds controls to XPages using drag and drop, the XML is generated automatically. XPages does not require any additional steps to install on a Domino server. When you create a new XPage in an application, you start with a blank page similar to what you see when a new form or page is created. You then build the XPage by dragging and dropping controls onto the XPage to add functionality. A wide array of controls is available out of the box, which enables application developers to quickly and easily get a web application up and running. Some examples of the controls available are a pager, rich text editor, date picker, tabbed panel, and many more. Controls can also be combined into a single object, called a custom control. Custom controls are similar to sub-forms, as they can be used in other XPages in the current application or copied into other applications for reuse. Just like with sub-forms, if a change is made to a custom control in an application, that change is propagated out to all other instances of that custom control in that application. There is a default system template in the 8.5 release that uses XPages. The discussion template has been enhanced to include XPages in 8.5. Improvements to CSS Support Now in Domino Designer 8.5 you can edit and create CSS. Previously, you would have to use an external editor to do this. Not only can you create custom stylesheets, but you can import existing ones. You can also group your favorite stylesheets and script resources into a theme to provide a common look and feel in your application and map style classes to UI controls. This will save developer time and effort when adding CSS to applications. To create a new stylesheet: Click File | New | Style Sheet Resource from the main Eclipse menu. In the New Style Sheet dialog box, do the following: In the Name field, type the name of the stylesheet. By default, Domino Designer adds a CSS file extension to this name In the Application field, select an application for the stylesheet. Click OK Another method of creating a stylesheet, is by double-clicking Resources | Style Sheets in the Applications navigator and then clicking New Style Sheet in the editor.
Read more
  • 0
  • 0
  • 8149

article-image-advanced-blog-management-apache-roller-40-part-1
Packt
03 Feb 2010
5 min read
Save for later

Advanced Blog Management with Apache Roller 4.0: Part 1

Packt
03 Feb 2010
5 min read
So let's get on with it. Managing group blogs Suddenly, your boss bursts into your office and shouts: "Well, let's give Roller a try for our company's blog!" And now, you have to enable group blogs in your Roller installation. Time for action – creating another user The first thing you need to do in order to enable group blogging is create another user, as shown in the following exercise: Open your web browser and type your Roller's dynamic hostname in the Address bar (for example, mine is http://alromero.no-ip.org). Now click on the Login link on your weblog's main page: The Welcome to Roller page will appear. Instead of logging in, click on the Register link in order to create a new user: The New User Registration screen will show up next. Fill in the fields for your new user, as shown in the following screenshot: Click on Register User when finished. If all goes well, you'll be taken back to the Welcome to Roller screen, and the following success message will appear: Select the Click here link to continue. Type your new Username and Password, and click on the Login button. The Main Menu page will appear: Click on the Create new weblog link, under the Actions panel. Roller will take you to the Create Weblog page. Fill in the required fields to create your new weblog. Use the following data for the Name, Description, and Handle fields: The Email Address field will already contain the e-mail address you used when creating your new user. Leave the default values for Locale, Timezone, and Theme, and click on the Create Weblog button to continue. The following page will appear indicating that your weblog was successfully created: Now click on the New Entry link in order to create the following new entry in your weblog: Scroll down the page and click on the Post to Weblog button to post your entry. What just happened? Well, now there's another user in your Roller server, how about that? Your boss is going to be proud of you and very happy, because your company will have a multiuser blog! The next step is to invite other people to create user accounts and weblogs in the Roller blog server. If you're using Roller in your office, just start spreading the word to your colleagues. Or if you're experimenting with Roller in your home, you can invite some friends to blog with you, create a family group blog, and so on. Have a go hero – inviting members to write in your weblog Now that you've learned how other people can register and get a user account in Roller, it would be a good idea to start exploring the Preferences: Members page, where you can invite other Roller users to collaborate in your weblog by posting entries. Roller has three user levels: Administrator: Can create/edit weblog entries and publish them in your weblog. An administrator can also change the Roller theme and templates, and manage weblog users. Author: Can create/edit weblog entries and upload files, but cannot change themes or templates, and cannot manage users. Limited: Can create/edit entries and save them as drafts, but cannot publish them. Go on and create several test user accounts, and try out the three Roller user levels by inviting the test users to collaborate in your weblog. To invite a user, use the Invite new member link under the Actions panel in the Preferences: Members page. Enabling a front page blog Up until now, you've been using your main weblog as the front page for your Roller blog server. Now that you've enabled group blogging, each user can promote his/her weblog(s) individually, or you can create a community front page to show recent posts from all of your user's weblogs. The next exercise will show you how to create and use a front page blog to show posts from all the other weblogs in your Roller blog server. Time for action – enabling a front page blog In this exercise, we're going to create a new weblog to serve as the front page of your entire Roller weblog server. The front page blog will show a list of recent entries from all your other weblogs, and from all the other users' weblogs in your Roller blog server. Log into Roller (in case you're not already logged in) with your administrator account, go to the Main Menu page, and then click on the Create new weblog link under the Actions panel: Type My Roller Community in the Name field, The best Roller blog community in the Description field, and frontpage in the Handle field: Scroll down the page until you locate the Theme field, select the Frontpage theme, and click on the Create Weblog button: The following page will appear, indicating that your frontpage weblog was created successfully: Now click on the Server administration link located in the Actions panel. The Roller Configuration page will show up. Scroll down until you locate the Handle of weblog to serve as frontpage blog field, and replace its contents with frontpage. Then click on the Enable aggregated site-wide frontpage option to enable it: Scroll down the page until you locate the Save button and click on it to save your changes. Now click on the Front Page link in Roller's menu bar:
Read more
  • 0
  • 0
  • 1855
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-rendering-images-typo3-43-part-2
Packt
03 Feb 2010
4 min read
Save for later

Rendering Images in TYPO3 4.3: Part 2

Packt
03 Feb 2010
4 min read
Rendering links to files using <media> tags Imagine, for a second, a dark world of web development without content management systems. You have a simple website with some text and links to files to be downloaded. Now, imagine that you need to move the files into a different folder. You would have to go through each page, and update the links to point to the new location of the file. In DAM, the physical file is separate from the record describing the file. Thanks to this separation, the pages can link to the DAM record, instead of the physical file. If the file is moved, only the DAM record will need to be updated (which happens automatically if you move the file within DAM modules), and all links will automatically update. We will now explore how the <media> HTML tag can be used to take advantage of this feature. Getting Ready Make sure both DAM and htmlArea RTE extensions are installed. In the Extension Manager click on the DAM extension to get an overview of enable configuration. Make sure that the media tag option is enabled. How to do it... Create a new Regular text element on a page. Enter the HTML mode in the RTE: Type in <media 1234>Link text</media>, replacing 1234 with the UID of the DAM record, and link the text with the text you want to appear inside the link. You can find the UID of the record in the information panel. Save and preview. How it works... The advantage of the <media> tag is that instead of linking to a file, you're linking to a DAM record. The record, in turn, points to the physical file—so if you move the files around, all links will be updated automatically. There's more It may be possible that after enabling all the options in the Extension Manager, the <media> tags are encoded by RTE, and appear in the frontend unparsed. In that case, you need to enter the following options in Page TSconfig: // Add txdam_media to RTE processing rulesRTE.default.proc.overruleMode = ts_css,txdam_media // Use same RTE processing rules in FERTE.default.FE.proc.overruleMode = ts_css,txdam_media // RTE processing rules for bodytext column of tt_content tableRTE.config.tt_content.bodytext.proc.overruleMode = ts_css,txdam_mediaRTE.config.tt_content.bodytext.types.text.proc.overruleMode = ts_css,txdam_mediaRTE.config.tt_content.bodytext.types.textpic.proc.overruleMode = ts_css,txdam_media Accessing Page TSconfig To access Page TSconfig, right-click on a page in the page tree, and choose Edit page properties: Alternatively, you can browse to the page in the Page module, and click the Edit page properties button either in the module body, or in the docheader —the bar across the top of the module housing the control buttons. From there, the Page TSConfig, is available under the Options tab: Creating a gallery using ce_gallery There are multiple galleries available for TYPO3. Each has its own advantages, and an entire book can be dedicated to comparing the various extensions. We will install and configure only one as an example. ce_gallery has an advantage that it is very easy to set up and customize, and relies completely on DAM for content and organization. Getting Ready Make sure you have the extensions DAM and dam_catedit installed. Create a root category, and a few categories under it. Assign a few JPG images to each category How to do it... Install ce_gallery. Accept database and filesystem changes. In a template record, include the static template Photogallery (CSS) (ce_gallery). Add a Plugin content element of type Photogallery to a page. In the General tab, uncheck the Slimbox (pmkslimbox needed) checkbox. In the Categories tab, select the root category and check the box that says Recursive: Save and preview. The output should appear similar to the following screenshot: How it works... ce_gallery treats DAM categories as albums, which in turn, contain pictures. If you want to add more photos to an album, just assign them to a category, and clear cache on the page where you added the Photogallery plugin.
Read more
  • 0
  • 0
  • 1844

article-image-rendering-images-typo3-43-part-1
Packt
03 Feb 2010
4 min read
Save for later

Rendering Images in TYPO3 4.3: Part 1

Packt
03 Feb 2010
4 min read
Rendering images using content elements Content elements offer a variety of ways for editors to include images. We will examine these here. Here is a typical selection menu that editor is presented with: A great way to start is to assemble pages from the Regular text element and the Text with image elements Getting Ready Make sure Content (default) is selected in Include static, and the CSS Styled Content template is included in the Include static (from extensions) field of the template record of the current page or any page above it in the hierarchy (page tree). To verify, go to the Template module, select the appropriate page, and click edit the whole template record. How to do it... Create the Text with image element. Under the Text tab, enter the text you want to appear on the page. You can use the RTE (Rich Text Editor) to apply formatting, or disable it. We will cover RTE in more detail later in this article. Under the Media tab, select your image settings. If you want to upload the image, use the first field. If you want to use an existing image, use the second field. Under Position, you are able to select where the image will appear in relation to the text. How it works... When the page is rendered in the frontend, the images will be placed next to the text you entered, in the position that you specify. The specific look will depend on the template that you are using. There's more An alternative to the Text with images is an Images only content element. This element gives you similar options, except limits the options to just a display of images. The rest of the options are the same. You can also resize the image, add caption, alt tags for accessibility and search engine optimization, and change default processing options. See the official TYPO3 documentation for details of how these fields work, (http://typo3.org/documentation/document-library/). See also Render video and audio using content elements and rgmediaimages extension Embedding images in RTE Rich Text Editor is great for text entry. By default, TYPO3 ships with htmlArea RTE as a system extension. Other editors are available, and can be installed if needed. Images can be embedded and manipulated within the RTE. This provides one place for content editors to use in order to arrange content how they want it to appear at the frontend of the site. In this recipe, we will see how this can be accomplished. The instructions apply to all forms that have RTE-enabled fields, but we will use the text content element for a simple demonstration. In the Extension Manager, click on htmlArea RTE extension to bring up its options. Make sure that the Enable images in the RTE [enableImages] setting is enabled. If you have a recent version of DAM installed (at least 1.1.0), make sure that the Enable the DAM media browser [enableDAMBrowser] setting is unchecked. This setting is deprecated, and is there for installations using older versions of DAM. How to do it... Create a new Regular text element content element. In the RTE, click on the icon to insert an image as shown in the following screenshot: Choose a file, and click on the icon to insert it into the Text area. You should see the image as it will appear at the frontend of the site. Save and preview. The output should appear similar to the following screenshot: How it works... When you insert an image through the RTE, the image is copied to uploads folder, and included from there. The new file will be resampled and sized down, so, it usually occupies less space and is downloaded faster than the original file. TYPO3 will automatically determine if the original file has changed, and update the file used in the RTE—but you should still be aware of this behaviour. Furthermore, if you have DAM installed, and you have included an image from DAM, you can see the updated record usage. If you view the record information, you should see the Content Element where the image is used:
Read more
  • 0
  • 0
  • 2250

article-image-advanced-blog-management-apache-roller-40-part-3
Packt
03 Feb 2010
4 min read
Save for later

Advanced Blog Management with Apache Roller 4.0: Part 3

Packt
03 Feb 2010
4 min read
Weblog clients There are times when logging into your Roller weblog to post a new entry can be a tedious process, especially when you have two or more weblogs about different subjects. Let's say that you have to write stuff in your company's blog, and you also write in your personal Roller blog. You can open two web browser windows and log into each blog separately, but it would be better to use a weblog client, as I'll show you in the next exercise. Time for action – using Google docs as your weblog client In this exercise, you'll learn to use Google docs as your weblog client to post entries in your Roller weblogs without having to log in: Open your web browser, go to http://docs.google.com, log in with your username and password (if you don't have a Google account, this is your chance to get one!), then click on the New button, and select the Document option: Your browser will open a new tab for the new Google docs document. Type This is my first post to my Roller weblog from Google Docs! in the word processor writing area, as shown in the following screenshot: Now click on the File menu and select the Save option to save your draft in Google docs: Google docs assigns the title for your document automatically, based on its content. To change the title of your post, click on it: Type Posting to Roller from Google Docs in the dialog that will show up next, and click on OK to continue: Google docs will show the new title for your post: Now click on the Share button and select the Publish as web page option: The Publish this document dialog will appear. Click on the change your blog site settings link to enter your Roller weblog information: The Blog Site Settings dialog will appear next. Choose the My own server / custom option and select MetaWeblog API in the API field. In the URL field you need to type the complete path to Roller's web services—http://alromero.noip.org/roller/roller-services/xmlrpc, in my case. You just need to replace the alromero.no-ip.org part with your dynamic hostname. Then type your Roller username, password, and weblog name, and select the Include the document title when posting option, as shown in the following screenshot: Click on the OK button to save your weblog settings, and then click on the Post to blog button in the Publish this document dialog: A confirmation dialog will pop-up, asking if you want to post the document to your blog now. Click on OK to continue: Google docs will show the This document has been published to your blog success message: Click on the Save & Close button at the upper-right part of the screen to save your document and return to the Google docs main page, then click on Sign out to exit Google docs. Now go to your Roller weblog's main page, to see the post you published from Google docs: What just happened? See how easy it is to use a weblog client, so that you don't need to log into your Roller weblog to post a new entry? And if you want to post to a different Roller weblog, you just need to change your username, blog ID, or URL. There are several other weblog clients available that you can use, depending on your operating system, but all weblog clients work in a similar way. Have a go hero – try out other weblog clients Go and try out some other weblog clients, to see which one is best for you. In Windows, you can use Windows Live Writer (http://download.live.com/writer) and w.bloggar (http://bloggar.com/). In Linux, you can try out BloGTK (https://launchpad.net/blogtk/).
Read more
  • 0
  • 0
  • 1871

article-image-advanced-blog-management-apache-roller-40-part-2
Packt
03 Feb 2010
4 min read
Save for later

Advanced Blog Management with Apache Roller 4.0: Part 2

Packt
03 Feb 2010
4 min read
Enabling weblog pings Now that you have a Technorati account, let's enable your Roller weblog so that it can ping Technorati automatically each time you post a new entry or edit a previously posted entry. Time for action – enabling automatic pings in your weblog This exercise will show you how to enable automatic pinging in your weblog, so that every time you post a new entry or update some entry you posted before, Technorati will receive a ping and will update your blog status: Go to the Front Page: Weblog Settings tab in your web browser, click on the Preferences tab to see your weblog's configuration page, and click on the Pings link: The Configure Automatic Weblog Pings page will appear next. Scroll down the page until you locate the Technorati row under the Common Ping Targets section: Click on Technorati's Enable link to enable automatic pinging for your weblog, so it can send automatic pings to Technorati: Click on the Send Ping Now button to test whether everything works correctly. Roller will show the following success message: Now you just have to wait until Technorati grabs your blog's most recent information, as shown in the following screenshot: What just happened? Now Technorati will keep your weblog information updated every time you post a new entry in your weblog. Once you register with an aggregator, it's very easy to configure automatic pinging in Roller, as you saw in the previous exercise. Now all you need to do is configure all the pings you can to other aggregators and blog search engines, so that people from everywhere can see your weblog! Have a go hero – configure more ping targets Now that you learned how to configure automatic pings to Technorati for your Roller weblog, check out the other ping targets available in the Common Ping Targets list. Go on and enable all the ping targets that you can in order to promote your weblog in all the available blog search engines and aggregators. You can also register with Digg, StumbleUpon, and the other popular aggregators/blog search engines and add new ping targets for them if you click on the Custom Ping Targets link in the Configure Automatic Weblog Pings page. So what are you waiting for? Go and promote your new Roller weblog! Google webmaster tools Now that you have a cool weblog, it would be great if the weblog would show up in Google every time someone searches for a subject related to the things you're writing, don't you think? That's why Google invented the webmaster tools—a great resource to help you find out how your weblog is interacting with the Google bot. With these tools you can get detailed information about broken links, popular keywords, and basically, all the stuff you need to have a successful weblog! Time for action – enabling Google webmaster tools This exercise will show you how to configure Google webmaster tools for your Roller weblog, so you can start receiving important information about visitors and how your weblog interacts with Google: Open your web browser and type https://www.google.com/webmasters/tools to go to the Google webmaster tools website: If you created a Gmail account when installing Roller, you can use it to sign in to Google webmaster tools. Or you can create a new Gmail account in case you don't have one already. Click on the Sign In button when ready. The Google webmaster tools Home page will appear next. Click on the Add a Site button at the bottom to add your Roller weblog: Now enter your weblog's URL in the pop-up box and click on Continue: Google will show you a Meta tag that you need to copy and paste in your Roller weblog. Select the meta tag, right-click on it, and click on Copy: Now open a new tab in your web browser, log into your Roller weblog, and go to the Design tab. The Weblog Theme page will appear. Click on the Custom Theme option and then on the Update Theme button: Roller will show the Successfully set theme to – custom message. Click on the Templates link and then select the Weblog template: Scroll down the page until you locate the </head> HTML tag and paste the Google webmaster tools meta tag right before it, as shown in the following screenshot: Scroll down the page until you locate the Save button and click on it. Roller will show the Template updated successfully message. Return to the Google webmaster tools tab in your web browser and click on the Verify button to verify your weblog: If all goes well, Google will verify your weblog and take you to the Dashboard:
Read more
  • 0
  • 0
  • 2113
article-image-typo3-connecting-external-apis-flicker-and-youtube
Packt
01 Feb 2010
10 min read
Save for later

TYPO3 for Connecting External APIs: Flicker and Youtube

Packt
01 Feb 2010
10 min read
Getting recent Flickr photos The Flickr API is very powerful and gives access to just about everything a user can do manually. You can write scripts to automatically download latest pictures from a photostream, download photos or videos tagged with a certain keyword, or post comments on photos. In this recipe, we will make use of the phpFlickr library to perform some basic listing functions for photos in Flickr. Getting ready Before you start, you should sign up for a free Flickr account, or use an existing one. Once you have the account, you need to sign up for an API key. You can go to Your Account, and select the Extending Flickr tab. After filling in a short form, you should be given two keys—API key and secret key. We will use these in all Flickr operations. We will not go through the steps required for integration into extensions, and will leave this exercise to the reader. The code we present can be used in both frontend plugins and backend modules. As was previously mentioned, we will be using the phpFlickr library. Go to http://phpflickr.com/ to download the latest version of the library and read the complete documentation. How to do it... Include phpFlickr, and instantiate the object (modify the path to the library, and replace api-key with your key): require_once("phpFlickr.php");$flickrService = new phpFlickr('api-key'); Get a list of photos for a specific user: $photos = $flickrService->people_getPublicPhotos('7542705@N08'); If the operation succeeds, $photos will contain an array of 100 (by default) photos from the user. You could loop over the array, and print a thumbnail with a link to the full image by: foreach ($photos['photos']['photo'] as $photo) { $imgURL = $flickrService->buildPhotoURL($photo, 'thumbnail'); print '<a href="http://www.flickr.com/photos/' . $photo['owner'] . '/' . $photo['id'] . '">' . '<img src="' . $imgURL . '" /></a><br />';} How it works... The Flickr API is exposed as a set of REST services, which we can issue calls to. The tough work of signing the requests and parsing the results is encapsulated by phpFlickr, so we don't have to worry about it. Our job is to gather the parameters, issue the request, and process the response. In the example above, we got a list of public photos from a user 7542705@N08. You may not know the user ID of the person you want to get photos for, but Flickr API offers several methods for finding the ID: $userID = $flickrService->people_findByEmail($email);$userID = $flickrService->people_findByUsername($username); If you have the user ID, but want to get more information about the user, you can do it with the following calls: // Get more info about the user:$flickrService->people_getInfo($userID);// Find which public groups the user belongs to:$flickrService->people_getPublicGroups($userID);// Get user's public photos:$flickrService->people_getPublicPhotos($userID); We utilize the people_getPublicPhotos method to get the user's photostream. The returned array has the following structure: Array( [photos] => Array ( [page] => 1 [pages] => 8 [perpage] => 100 [total] => 770 [photo] => Array ( [0] => Array ( [id] => 3960430648 [owner] => 7542705@N08 [secret] => 9c4087aae3 [server] => 3423 [farm] => 4 [title] => One Cold Morning [ispublic] => 1 [isfriend] => 0 [isfamily] => 0 ) […] ) )) We loop over the $photos['photos']['photo'] array, and for each image, we build a URL for the thumbnail using the buildPhotoURL method, and a link to the image page on Flickr. There's more... There are lots of other things we can do, but we will only cover a few basic operations. Error reporting and debugging Occasionally, you might encounter an output you do not expect. It's possible that the Flickr API returned an error, but by default, it's not shown to the user. You need to call the following functions to get more information about the error: $errorCode = $flickrService->getErrorCode();$errorMessage = $flickrService->getErrorMsg(); Downloading a list of recent photos You can get a list of the most recent photos uploaded to Flickr using the following call: $recentPhotos = $flickrService->photos_getRecent(); See also Uploading files to Flickr Uploading DAM files to Flickr Uploading files to Flickr In this recipe, we will take a look at how to upload files to Flickr, as well as how to access other authenticated operations. Although many operations don't require authentication, any interactive functions do. Once you have successfully authenticated with Flickr, you can upload files, leave comments, and make other changes to the data stored in Flickr that you wouldn't be allowed to do without authentication. Getting ready If you followed the previous example, you should have everything ready to go. We'll assume you have the $flickrService object instantiated ready. How to do it... Before calling any operations that require elevated permissions, the service needs to be authenticated. Add the following code to perform the authentication: $frob = t3lib_div::_GET('frob');if (empty($frob)) { $flickrService->auth('write', false);} else { $flickrService->auth_getToken($frob);} Call the function to upload the file: $flickrService->sync_upload($filePath); Once the file is uploaded, it will appear in the user's photostream. How it works... Flickr applications can access any user's data if the user authorizes them. For security reasons, users are redirected to Yahoo! to log into their account, and confirm access for your application. Once your application is authorized by a user, a token is stored in Flickr, and can be retrieved at any other time. $flickrService->auth() requests permissions for the application. If the application is not yet authorized by the user, he/she will be redirected to Flickr. After giving the requested permissions, Flickr will redirect the user to the URL defined in the API key settings. The redirected URL will contain a parameter frob. If present, $flickrService->auth_getToken($frob); is executed to get the token and store it in session. Future calls within the session lifetime will not require further calls to Flickr. If the session is expired, the token will be requested from Flickr service, transparent to the end user. There's more... Successful authentication allows you to access other operations that you would not be able to access using regular authentication. Gaining permissions There are different levels of permissions that the service can request. You should not request more permissions than your application will use. API call Permission level $flickrService->auth('read', false); Permissions to read users' files, sets, collections, groups, and more. $flickrService->auth('write', false); Permissions to write (upload, create new, and so on). $flickrService->auth('delete', false); Permissions to delete files, groups, associations, and so on. Choosing between synchronous and asynchronous upload There are two functions that perform a file upload: $flickrService->sync_upload($filePath);$flickrService->async_upload($filePath); The first function continues execution only after the file has been accepted and processed by Flickr. The second function returns after the file has been submitted, but not necessarily processed. Why would you use the asynchronous method? Flickr service may have a large queue of uploaded files waiting to be processed, and your application might timeout while it's waiting. If you don't need to access the uploaded file right after it was uploaded, you should use the asynchronous method. See also Getting recent Flickr photos Uploading DAM files to Flickr Uploading DAM files to Flickr In this recipe, we will make use of our knowledge of the Flickr API and the phpFlickr interface to build a Flickr upload service into DAM. We will create a new action class, which will add our functionality into a DAM file list and context menus. Getting ready For simplicity, we will skip the process of creating the extension. You can download the extension dam_flickr_upload and view the source code. We will examine it in more detail in the How it works... section. How to do it... Sign up for Flickr, and request an API key if you haven't already done so. After you receive your key, click Edit key details. Fill in the application title and description as you see fit. Under the call back URL, enter the web path to the dam_flickr_upload/mod1/index.php file. For example, if your domain is http://domain.com/, TYPO3 is installed in the root of the domain, and you installed dam_flickr_upload in the default local location under typo3conf, then enter http://domain.com/typo3conf/ext/dam_flickr_upload/mod1/index.php You're likely to experience trouble with the callback URL if you're doing it on a local installation with no public URI. Install dam_flickr_upload. In the Extension Manager, under the extension settings, enter the Flickr API key and the secret key you have received. Go to the Media | File module, and click on the control button next to a file. Alternatively, select Send to Flickr in the context menu, which appears if you click on the file icon, as seen in the following screenshot: A new window will open, and redirect you to Flickr, asking you to authorize the application for accessing your account. Confirm the authorization by clicking the OK, I'LL AUTHORIZE IT button. The file will be uploaded, and placed into your photostream on Flickr. Subsequent uploads will no longer need explicit authorization. A window will come up, and disappear after the file has been successfully uploaded. How it works... Let's examine in detail how the extension works. First, examine the file tree. The root contains the now familiar ext_tables.php and ext_conf_template.txt files.The Res directory contains icons used in the DAM. The Lib directory contains the phpFlickr library. The Mod1 directory contains the module for uploading. ext_conf_template.txt This file contains the global extension configuration variables. The two variables defined in this file are the Flickr API key and the Flickr secret key. Both of these are required to upload files. ext_tables.php As was mentioned previously, ext_tables.php is a configuration file that is loaded when the TYPO3 framework is initializing. tx_dam::register_action ('tx_dam_action_flickrUpload', 'EXT:dam_flickr_upload/class.tx_dam_flickr_upload_action.php:&tx_dam_flickr_upload_action_flickrUpload'); This line registers a new action in DAM. Actions are provided by classes extending the tx_dam_actionbase class, and define operations that can be performed on files and directories. Examples of actions include view, cut, copy, rename, delete, and more. The second parameter of the function defines where the action class is located. $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['dam_flickr_upload']['allowedExtensions'] = array('avi', 'wmv', 'mov', 'mpg', 'mpeg','3gp', 'jpg', 'jpeg', 'tiff', 'gif', 'png'); We define an array of file types that can be uploaded to Flickr. This is not hardcoded in the extension, but stored in ext_tables.php, so that it can be overwritten by extensions wanting to limit or expand the functionality to other file types.
Read more
  • 0
  • 0
  • 2760

article-image-magentos-architecture-part-2
Packt
01 Feb 2010
7 min read
Save for later

Magento's Architecture: Part 2

Packt
01 Feb 2010
7 min read
Modules and how they work within the system Magento primarily works on a base of modules. All functionality is divided up into modules that make up the system overall. It's important to understand what each module does and how to go about adding modules to the system, in order to understand the architecture of modules themselves. Distribution of the modules between directories All modules are located within the /app/code/ directory. Directories are commonly referred to as codePools. There are three possible locations for all modules that relate to the system. They are all split by type to prevent any confusion: community—For community-distributed extensions, usually those that we have installed through Magento Connect or have downloaded from a source, other than our own. Anything installed through Magento Connect will be installed here automatically. core—Reserved for core Magento modules, so that we cannot directly overwrite or interfere with them. We keep our modules out of core to avoid any conflict with the core modules or any future updates. Anything from a Magento upgrade or any new Magento modules will go into this directory. Local—This is where we should be placing our modules when they are either under local development or are not distributed among the community. It's best to keep anything that we develop in this directory, so as to not interfere with the core or community modules. Nothing will be automatically installed here, unless we have physically uploaded it. Modules included with Magento Included modules in the core folder of default Magento installation are as follows: Mage_Admin Mage_AdminNotification Mage_Api Mage_Backup Mage_Bundle Mage_Catalog Mage_CatalogIndex Mage_CatalogInventory Mage_CatalogRule Mage_CatalogSearch Mage_Checkout Mage_Cms Mage_Contacts Mage_Core Mage_Cron Mage_Customer Mage_Dataflow Mage_Directory Mage_Downloadable Mage_Eav Mage_GiftMessage Mage_GoogleAnalytics Mage_GoogleBase Mage_GoogleCheckout Mage_GoogleOptimizer Mage_Install Mage_Log Mage_Media Mage_Newsletter Mage_Page Mage_Paygate Mage_Payment Mage_Paypal Mage_PaypalUk Mage_Poll Mage_ProductAlert Mage_Rating Mage_Reports Mage_Review Mage_Rss Mage_Rule Mage_Sales Mage_SalesRule Mage_Sendfriend Mage_Shipping Mage_Sitemap Mage_Tag Mage_Tax Mage_Usa Mage_Weee Mage_Wishlist Setting up the folder structure of a module Let's presume that we want to set up a module's folder structure, ready for development. Our module's core folders will be placed in /app/code/local/Book/Example/. These folders will primarily be used for storing our code that makes the module work. The folder structure breaks down as follows: Block/ controllers/ etc/ Model/ Mysql4/ Book/ sql/ book_setup/ Typically, developers will pick or choose each folder, depending on whether or not they're going to use it within their module. Note that Model/Mysql4/Book/ has its first letter in uppercase, whereas sql/book_setup/ does not. We must be sure to keep this the same way throughout our development. Template files for the frontend of our module will be stored as follows: XML files will be stored in /app/design/frontend/<interface>/<theme>/layout/example/ Output files will be stored in /app/design/frontend/<interface>/<theme>/template/example/ Any admin template files for the frontend of our module will be stored as follows: XML files will be stored in /app/design/adminhtml/<interface>/<theme>/layout/example/ Output files will be stored in /app/design/adminhtml/<interface>/<theme>/template/example/ Here's a breakdown of what each folder is for: Block/—For processing of all display blocks called by the system for the module. These are controllers that will be called in the XML layout files within a theme, in order to display something. controllers/—Our controllers that support the application and structurally keep things together. etc/—Configuration files for the module, for declaring things such as the default options when installed and declaring all blocks, models, and install/upgrade actions. Model/—For placement of all models to support controllers in the module. sql/—SQL actions when the module is installed/upgraded/uninstalled. Zend Framework and its role within Magento Magento (at its raw PHP base) is built on the Zend Framework. From the database class to the handling of URLs, Magento is in its raw form, with Zend Framework doing all the work. Alongside this, Varien has built several core modules on top of the Zend Framework, in order to tie it altogether into the system as we know it. What is Zend Framework Zend Framework's official site best describes the framework as follows: Zend Framework (ZF) is an open source framework for developing web applications and services with PHP 5. ZF is implemented using 100% object-oriented code. The component structure of ZF is somewhat unique; each component is designed with few dependencies on other components. This loosely coupled architecture allows developers to use components individually. We often call this a "use-at-will" design. While they can be used separately, Zend Framework components in the standard library form a powerful and extensible web application framework when combined. ZF offers a robust, high performance MVC implementation, a database abstraction that is simple to use, and a forms component that implements HTML form rendering, validation, and filtering so that developers can consolidate all of these operations using one easy-to-use, object-oriented interface. Other components, such as Zend_Auth and Zend_Acl, provide user authentication and authorization against all common credential stores. Still others implement client libraries to simply access to the most popular web services available. Whatever your application needs are, you're likely to find a Zend Framework component that can be used to dramatically reduce development time with a thoroughly tested foundation. How Zend Framework works The Zend Framework (at its core) is designed to be used as a package or separate modules. This (among other features) makes it unique, as most other frameworks are designed to be used plainly as frameworks or not at all. However, the Zend Framework comes with classes that allow us to use it as a standalone framework and develop with it as one. Instead of being delivered with a preset amount of directories and layout for developers, it only suggests a layout for our files. This means that we can adapt the framework to meet our current workflow and choose how much we adapt the workflow to fit the framework. It's role and effect in Magento The Zend Framework allows Magento to focus on the core issues at hand. It removes a lot of the work on the database and core structural classes and puts the work towards fixing and adding to core modules of Magento. Most importantly it gives developers a standard approach to development that they can move across and apply to Magento. The standard development practices help greatly in adopting Magento as a platform and make it easier for developers having experience with Zend Framework to adapt to Magento. More information on learning the Zend Framework and resources can be found at the back of this book in the Appendix attached. Its official site is located at: http://framework.zend.com/. Backing up Magento's data It's important to know how to back up our site, to ensure that our installation's data is not lost (if ever things go bad). It is recommended to back up our Magento installation: Regularly as a base to ensure that there are incremental backups of our system Before installing new modules or themes from Magento Connect When developing modules Before upgrading our system
Read more
  • 0
  • 0
  • 1998

article-image-magentos-architecture-part-1
Packt
01 Feb 2010
5 min read
Save for later

Magento's Architecture: Part 1

Packt
01 Feb 2010
5 min read
Magento's base structure The fundamental knowledge of Magento's architecture begins with its file structure. It's important to know what goes where by default, so that we may position our new files accordingly, especially in terms of ensuring that our development doesn't overwrite core files. Base directory The default installation contains the following files and directories in the base directory: .htaccess .htaccess.sample 404 (directory) app (directory) cron.php downloader (directory) favicon.ico index.php index.php.sample js (directory) lib (directory) LICENSE_AFL.txt LICENSE.txt media (directory) pear pkginfo (directory) report (directory) skin (directory) var (directory) Each of these files and directories has a different purpose. We'll go through them to ensure that we understand the function of each. This will help us later, if ever we need to find something specific, or when developing. It will also be helpful when we'll be looking to place the files coming out of our new module into the appropriate directory. The function of each of the files in the base directory The following is a run through of all the files in the base directory, to show us what they do: .htaccess—This file controls mod_rewrite for fancy URLs and sets configuration server variables (such as memory limit) and PHP maximum execution time, so that Magento can run better. .htaccess.sample—Works as a backup for .htaccess, so that we know the default .htaccess file (if ever we edit it and need to backtrack). cron.php—The file that should be executed as a cron job every few minutes to ensure that Magento's wide caching doesn't affect our server's performance. favicon.ico—Magento's default favicon; it's the small icon that appears in the toolbar of our browser. index.php—The main loader file for Magento and the file that initializes everything. index.php.sample—The base template for new index.php files, useful when we have edited the index.php file and need to backtrack. LICENSE_AFL.txt—It contains the Academic Free License that Magento is distributed under. LICENSE.txt—It contains the Open Software License that Magento is distributed under. pear—This controls all automatic updating via the downloader and SSH. This file is initialized and handles the updating of each individual module that makes up Magento. php.ini—A sample php.ini file for raw PHP server variables recommended when setting up Magento on our server. This should not be used as a complete replacement, but only as a guide to replace certain lines of the php.ini server file. It is useful when overriding these variables when .htaccess isn't enabled on our server. The function of each of the folders in the base directory The following is a run through of all the folders in the base directory to show us their contents: 404—The default 404 template and skin storage folder for Magento. app—All code (modules), design (themes), configuration, and translation files are stored in this directory. This is the folder that we'll be working in extensively, when developing a Magento powered website. Also contained in this folder are the template files for the default administration theme and installation. downloader—The web downloader for upgrading and installing Magento without the use of SSH. js—The core folder where all JavaScript code included with the installation of Magento is kept. We will find all pre-compiled libraries of JavaScript here. lib—All PHP libraries used to put together Magento. This is the core code of Magento that ties everything together. The Zend Framework is also stored within this directory. media—All media is stored here. Primarily for images out of the box, this is where all generated thumbnails and uploaded product images will be stored. It is also the container for importing images, when using the mass import/export tools. pkginfo—Short form of package information, this directory contains text files that largely operate as debug files to inform us about changes when modules are upgraded in any way. report—The skin folder for the reports that Magento outputs when any error occurs. skin—All assets for themes are stored within this directory. We typically find images, JavaScript files, CSS files, and Flash files relating to themes, in this directory. However, it can be used to store any assets associated with a theme. It also contains the skin files for the installation of skins and administration templates. var—Typically where we will find all cache and generated files for Magento. We can find the cache, sessions (if storing as files), data exports, database backups, and cached error reports in this folder. The template system architecture The template architecture is broken into three areas—two for development of the theme and one for the containment of the assets: /app/design/frontend/default/<template_name>/ layout/—For all the XML files declaring which module tied functions should be called to which template files template/—For all the templates processing the output that is passed from functions called from layout/ and structured into the final output to the user. /skin/frontend/default/<template_name>/—For the containment of all assets relating to our template, images, CSS, Flash, and JavaScript. Structural blocks and content blocks Each theme contains structural and content blocks. Structural blocks are the ones that lay out the theme into sections. Let's take a look at a three-column layout. The following are the structural blocks in a three-column layout: header left content right footer Here's a visual representation of those structural blocks laid over the Magento demo store: In each of the structural blocks, we then have content blocks that give each structural block its content for output to the browser. Let's take the right column; our content blocks set for this column on a standard theme could be: mini cart recently viewed products newsletter subscription block poll
Read more
  • 0
  • 0
  • 6646
article-image-embedding-doctests-python-docstrings
Packt
29 Jan 2010
12 min read
Save for later

Embedding Doctests in Python Docstrings

Packt
29 Jan 2010
12 min read
Doctests aren't confined to simple text files. You can put doctests into Python's docstrings. Why would you want to do that? There are a couple of reasons. First of all, docstrings are an important part of the usability of Python code (but only if they tell the truth). If the behavior of a function, method, or module changes and the docstring doesn't get updated, then the docstring becomes misinformation, and a hindrance rather than a help. If the docstring contains a couple of doctest examples, then the out-of-date docstrings can be located automatically. Another reason for placing doctest examples into docstrings is simply that it can be very convenient. This practice keeps the tests, documentation and code all in the same place, where it can all be located easily. If the docstring becomes home to too many tests, this can destroy its utility as documentation. This should be avoided; if you find yourself with so many tests in the docstrings that they aren't useful as a quick reference, move most of them to a separate file. Time for action – embedding a doctest in a docstring We'll embed a test right inside the Python source file that it tests, by placing it inside a docstring. Create a file called test.py with the following contents: def testable(x): r""" The `testable` function returns the square root of its parameter, or 3, whichever is larger. >>> testable(7) 3.0 >>> testable(16) 4.0 >>> testable(9) 3.0 >>> testable(10) == 10 ** 0.5 True """ if x < 9: return 3.0 return x ** 0.5 At the command prompt, change to the directory where you saved test.py and then run the tests by typing: $ python -m doctest test.py As mentioned earlier before, if you have an older version of Python, this isn't going to work for you. Instead, you need to type python -c "__import__('doctest').testmod(__import__('test'))" If everything worked, you shouldn't see anything at all. If you want some confirmation that doctest is doing something, turn on verbose reporting by changing the command to: python -m doctest -v test.py For older versions of Python, instead use python -c "__import__('doctest').testmod(__import__('test'), verbose=True)" What just happened You put the doctest right inside the docstring of the function it was testing. This is a good place for tests that also show a user how to do something. It's not a good place for detailed, low-level tests (the above example, which was quite detailed for illustrative purposes, is skirting the edge of being too detailed), because docstrings need to serve as API documentation. You can see the reason for this just by looking back at the example, where the doctests take up most of the room in the docstring, without telling the readers any more than they would have learned from a single test. Any test that will serve as good API documentation is a good candidate for including in the docstrings. Notice the use of a raw string for the docstring (denoted by the r character before the first triple-quote). Using raw strings for your docstrings is a good habit to get into, because you usually don't want escape sequences—e.g. n for newline—to be interpreted by the Python interpreter. You want them to be treated as text, so that they are correctly passed on to doctest. Doctest directives Embedded doctests can accept exactly the same directives as doctests in text files can, using exactly the same syntax. Because of this, all of the doctest directives that we discussed before can also be used to aff ect the way embedded doctests are evaluated. Execution scope Doctests embedded in docstrings have a somewhat different execution scope than doctests in text files do. Instead of having a single scope for all of the tests in the file, doctest creates a single scope for each docstring. All of the tests that share a docstring, also share an execution scope, but they're isolated from tests in other docstrings. The separation of each docstring into its own execution scope often means that we don't need to put much thought into isolating doctests, when they're embedded in docstrings. That is fortunate, since docstrings are primarily intended for documentation, and the tricks needed to isolate the tests might obscure the meaning. Putting it in practice: an AVL tree We'll walk step-by-step through the process of using doctest to create a testable specification for a data structure called an AVL Tree. An AVL tree is a way to organize key-value pairs, so that they can be quickly located by key. In other words, it's a lot like Python's built-in dictionary type. The name AVL references the initials of the people who invented this data structure. As its name suggests, an AVL tree organizes the keys that are stored in it into a tree structure, with each key having up to two child keys—one child key that is less than the parent key by comparison, and one that is more. In the following picture, the key Elephant has two child keys, Goose has one, and Aardvark and Frog both have none. The AVL tree is special, because it keeps one side of the tree from getting much taller than the other, which means that users can expect it to perform reliably and efficiently no matter what. In the previous image, an AVL tree would reorganize to stay balanced if Frog gained a child. We'll write tests for an AVL tree implementation here, rather than writing the implementation itself. Therefore, we'll elaborate over the details of how an AVL tree works, in favor of looking at what it should do when it works right If you want to know more about AVL Trees, you will find many good references on the Internet. Wikipedia's entry on the subject is a good place to start with:http://en.wikipedia.org/wiki/AVL_tree. We'll start with a plain language specification, and then interject tests between the paragraphs. You don't have to actually type all of this into a text file; it is here for you to read and to think about. English specification The first step is to describe what the desired result should be, in normal language. This might be something that you do for yourself, or something that somebody else does for you. If you're working for somebody, hopefully you and your employer can sit down together and work this part out. In this case, there's not much to work out, because AVL Trees have been fully described for decades. Even so, the description here isn't quite like one you'd find anywhere else. This capacity for ambiguity is exactly the reason why a plain language specification isn't good enough. We need an unambiguous specification, and that's exactly what the tests in a doctest file can give us. The following text goes in a file called AVL.txt, (which you can find in its final form in the accompanying code archive. At this stage of the process, the file contains only the normal language specification.): An AVL Tree consists of a collection of nodes organized in a binarytree structure. Each node has left and right children, each of whichmay be either None or another tree node. Each node has a key, whichmust be comparable via the less-than operator. Each node has a value.Each node also has a height number, measuring how far the node is frombeing a leaf of the tree -- a node with height 0 is a leaf.The binary tree structure is maintained in ordered form, meaning thatof a node's two children, the left child has a key that comparesless than the node's key and the right child has a key that comparesgreater than the node's key.The binary tree structure is maintained in a balanced form, meaningthat for any given node, the heights of its children are either thesame or only differ by 1.The node constructor takes either a pair of parameters representinga key and a value, or a dict object representing the key-value pairswith which to initialize a new tree.The following methods target the node on which they are called, andcan be considered part of the internal mechanism of the tree:Each node has a recalculate_height method, which correctly sets theheight number.Each node has a make_deletable method, which exchanges the positionsof the node and one of its leaf descendants, such that the the treeordering of the nodes remains correct.Each node has rotate_clockwise and rotate_counterclockwise methods.Rotate_clockwise takes the node's right child and places it wherethe node was, making the node into the left child of its own formerchild. Other nodes in the vicinity are moved so as to maintainthe tree ordering. The opposite operation is performed by rotate_counterclockwise.Each node has a locate method, taking a key as a parameter, whichsearches the node and its descendants for a node with the specifiedkey, and either returns that node or raises a KeyError.The following methods target the whole tree rooted at the currentnode. The intent is that they will be called on the root node:Each node has a get method taking a key as a parameter, which locatesthe value associated with the specified key and returns it, or raisesKeyError if the key is not associated with any value in the tree.Each node has a set method taking a key and a value as parameters, andassociating the key and value within the tree.Each node has a remove method taking a key as a parameter, andremoving the key and its associated value from the tree. It raisesKeyError if no values was associated with that key. Node data The first three paragraphs of the specification describe the member variables of a AVL tree node, and tell us what the valid values for the variables are. They also tell us how tree height should be measured and define what a balanced tree means. It's our job now to take up those ideas, and encode them into tests that the computer can eventually use to check our code. We could check these specifications by creating a node and then testing the values, but that would really just be a test of the constructor. It's important to test the constructor, but what we really want to do is to incorporate checks that the node variables are left in a valid state into our tests of each member function. To that end, we'll define a function that our tests can call to check that the state of a node is valid. We'll define that function just after the third paragraph: Notice that this test is written as if the AVL tree implementation already existed. It tries to import an avl_tree module containing an AVL class, and it tries to use the AVL class is specific ways. Of course, at the moment there is no avl_tree module, so the test will fail. That's as it should be. All that the failure means is that, when the ti me comes to implement the tree, we should do so in a module called avl_tree, with contents that function as our test assumes. Part of the benefit of testing like this is being able to test-drive your code before you even write it. >>> from avl_tree import AVL>>> def valid_state(node):... if node is None:... return... if node.left is not None:... assert isinstance(node.left, AVL)... assert node.left.key < node.key... left_height = node.left.height + 1... else:... left_height = 0...... if node.right is not None:... assert isinstance(node.right, AVL)... assert node.right.key > node.key... right_height = node.right.height + 1... else:... right_height = 0...... assert abs(left_height - right_height) < 2... node.key < node.key... node.value>>> def valid_tree(node):... if node is None:... return... valid_state(node)... valid_tree(node.left)... valid_tree(node.right) Notice that we didn't actually call those functions yet. They aren't tests, per se, but tools that we'll use to simplify writing tests. We define them here, rather than in the Python module that we're going to test, because they aren't conceptually part of the tested code, and because anyone who reads the tests will need to be able to see what the helper functions do. Constructor The fourth paragraph describes the constructor for an AVL node: The node constructor takes either a pair of parameters representing a key and a value, or a dict object representing the key-value pairs with which to initialize a new tree. The constructor has two possible modes of operation: it can either create a single initialized node or it can create and initialize a whole tree of nodes. The test for the single node mode is easy: >>> valid_state(AVL(2, 'Testing is fun')) The other mode of the constructor is a problem, because it is almost certain that it will be implemented by creating an initial tree node and then calling its set method to add the rest of the nodes. Why is that a problem? Because we don't want to test the set method here: this test should be focused entirely on whether the constructor works correctly, when everything it depends on works. In other words, the tests should be able to assume that everything outside of the specific chunk of code being tested works correctly. However, that's not always a valid assumption. So, how can we write tests for things that call on code outside of what's being tested? There is a solution for this problem. For now, we'll just leave the second mode of operation of the constructor untested.
Read more
  • 0
  • 0
  • 12494

article-image-shipping-modules-magento-part-1
Packt
29 Jan 2010
10 min read
Save for later

Shipping Modules in Magento: Part 1

Packt
29 Jan 2010
10 min read
What shipping modules do Shipping modules are used to define the handling of the order, before it goes through the payment method section of the order process. They take the order itself and decide how to go about charging and delivering it to the customer. Magento takes the order through each shipping module that is installed and active in the system. Each shipping module is then able to process the order currently in the cart and present any available options to the user, from what it sees in the order. For example: we have a shipping module in our system that provides free delivery to people located within the UK and ordering over £40. Let's presume that we are ordering £50 worth of goods and are located within the UK. When the order is sent through this module, it checks whether or not the user is in the UK and the order total is over £40. If these conditions are met, (which our order does), then we are presented with a free delivery option, among others, to choose during our order process. This is a very simple version of what a shipping module can do. The full range of what can be done using shipping modules can be grasped by looking at Shipping Modules on Magento Connect and finding what it has on offer. Here's a small range of what has been made public: Royal Mail UK, EU, and Worldwide Shipping module — For calculation and handling of all of Royal Mail's shipping methods using weight and distance. This module sends key product information to Royal Mail via their API, authenticating with information that the Magento store administrator has input, and outputs pricing for various shipping options on the current order. Regional Free Shipping module — Gives the Magento administrator the option to allow free shipping by region, instead of by country. This provides a choice to the store administrator of breaking down free shipping further than country. For example, this would be good for someone who runs a store based in Nottingham that wants to reward local customers in the East Midlands, as opposed to simply giving free shipping to the entire United Kingdom. Basic Store Pickup Shipping module — Enables customers to choose between picking up the item themselves and having it delivered to them. This is advantageous for companies which use Magento and have a physical store presence with stock held. Magento Connect can be accessed at the following URL:http://www.magentocommerce.com/magento-connect. The three core types of shipping module can be summarized in the following: Third-party API and/or web service integration. For integration with existing couriers that have web-based APIs or web services that offer the same for organization of your shipping. Many existing services make an API available to us for integrating into Magento. We should check Magento Connect for any existing modules that others have created. Using customer data to provide unique calculations and opportunities to certain users. Anything that the customer puts in it while checking out can be used for this type of module. Shipping methods that involve a physical store or location for additional options that compliment others. We could theoretically build up a set of stores under the Magento store company's business. We could then link them up with local computers at the locations and use the shipping module to check for stocks at each location. We should do that before suggesting the store as a location for the user to be able to pick up the item. How to begin with a shipping module Here we'll be learning about how to begin with a shipping module. This is the skeletal structure of a shipping module that we can use as a template for any shipping module which we create. We will also be using it to create a very basic shipping module at the end of this article. For the purpose of following this tutorial, we will be creating all files in /app/code/local/MagentoBook/ShippingModule/ , which will be the base directory for all files created (from this point onwards). We must make sure that this directory and sub-directory are set up before continuing onwards. This means that if the file is declared to be /hello/world.php, we place this on the end of our initial base address and it becomes /app/code/local/MagentoBook/ShippingModule/hello/world.php Please start by creating the directory MagentoBook in /app/code/local/ and a sub-directory within that called ShippingModule, creating the directory structure /MagentoBook/ShippingModule/. The configuration files We create /app/code/local/MagentoBook/ShippingModule/etc/config.xml in our module's folder. Here, we'll place the following code which will declare our new module for use, make it depend on Mage_Shipping being enabled, set it at version 0.1.0 and allow it to use the existing global database connection which is set up for our store. <?xml version="1.0"?><config> <modules> <MagentoBook_ShippingModule> <version>0.1.0</version> <depends> <Mage_Shipping /> </depends> </MagentoBook_ShippingModule> </modules> <global> <models> <shippingmodule> <class>MagentoBook_ShippingModule_Model</class> </shippingmodule> </models> <resources> <shippingmodule_setup> <setup> <module>MagentoBook_ShippingModule</module> </setup> <connection> <use>core_setup</use> </connection> </shippingmodule_setup> </resources> </global> <default> <carriers> <shippingmodule> <model>MagentoBook/carrier_ShippingModule</model> </shippingmodule> </carriers> </default></config> Let's walk back through this code and go over what each individual section does. We start by defining our XML header tag for the file, to ensure that it is accepted as an XML file when read by the XML parsing class in the system. <?xml version="1.0"?> We define the <config> tag, to ensure that everything within it is read as configuration variables to be loaded into Magento's configuration for whatever we define internally within this tag. <config> We define the <modules> tag, so that we're setting configuration variables for modules defined within this tag. <modules> <MagentoBook_ShippingModule> We set the module's version number to 0.1.0, to supply Magento with versioning for the module in the future, if we update and need to perform statements within the update portion of the module, so as to execute above a certain version number. <version>0.1.0</version> We have to make sure that our module cannot be activated, or possibly run, without the Mage_Shipping core shipping handler and module activated. This is vital because the module being a shipping module is simply going to cause fatal errors without the parent Mage_Shipping module providing the helper functions needed internally. <depends> <Mage_Shipping /></depends> Next, we close off our module declaration tag and modules tag. </MagentoBook_ShippingModule></modules> We set up our <global> tag to define global assets to Magento. <global> Next, we define the <models> tag to define global models to the system and for setting up our module's default model to be one of those global models which is automatically loaded. <models> <shippingmodule> <class>MagentoBook_ShippingModule_Model</class> </shippingmodule></models> Next, we define the <resources>tag, so that we can configure the database resources available to the module within the system. <resources> Defining the <resources> tag allows us to include a setup file with our module that accesses the database. This helps if we need to load in any variables (such as default table rate rules) for our module, or for loading additional data required locally by the module, when calculating the shipping rates. <shippingmodule_setup> <setup> <module>MagentoBook_ShippingModule</module> </setup> Here, we'll use the core database connection (the default one), and ensure that we do not overwrite the database connection set up for this particular module. <connection> <use>core_setup</use> </connection> We close off all tag pairs, besides <config>, that have been opened at this point. </shippingmodule_setup> </resources></global> Finally, we end the configuration file with a declaration that our module is a shipping module and should be processed as one, within the system. This will register the module to the system, so that it can actually display shipping methods to the user on checkout. Without this, nothing will be returned to the user from this module. <default> <carriers> <shippingmodule> <model>MagentoBook/carrier_ShippingModule</model> </shippingmodule> </carriers></default> We close the <config> tag to end the XML configuration file. </config> After we've done this, we need to declare our module to Magento by creating a configuration file in /app/etc/modules/MagentoBook_ShippingModule.xml. Next, we place the following code in our new configuration file, to allow this module to interact with Magento and be turned on/off under the System Configuration menu: <?xml version="1.0"?><config> <modules> <MagentoBook_ShippingModule> <active>true</active> <codePool>local</codePool> </MagentoBook_ShippingModule> </modules></config> We break this file down into the individual lines: <?xml version="1.0"?> The <config> wrapper tag defines the XML to be read, as a configuration of something inside Magento. <config> The <modules> wrapping tag defines this as a module to Magento. <modules> The next tag is used for defining that this is the configuration of a module entitled <MagentoBook_ShippingModule> and for applying the settings inside the tag to the module: <MagentoBook_ShippingModule> We make sure that it's active by default (this will be overwritten when activated/deactivated in the Magento administrative back-end). <active>true</active> The <code pool> tag is used for keeping this module in our local module's directory. <codePool>local</codePool> Closing tags are for closing the XML tags that we started the <config> tag with. </MagentoBook_ShippingModule> </modules></config> Now that we have the configuration set up, to allow the module to be managed within Magento and versioning control to allow for upgrades in the future, we can progress onto the module itself. It also means that we can now turn our module on/off within the administration. To do this, we go to System|Configuration , then to Advanced under the Advanced heading on the left-hand side. Once here, we will be presented Enable/Disable dropdowns for each module installed in the system. We'll set the dropdown for our module to Disable until we have completed the adaptor model and administration setup. This will prevent the module from crashing the system, while it is incomplete. We will re-activate the module once we're ready to see the output.
Read more
  • 0
  • 0
  • 2487
Modal Close icon
Modal Close icon