Permalink
Browse files

initial checkin

  • Loading branch information...
0 parents commit 358879057f5e50219ab7f1ae0a47ca25bcb9fd3a @timcase timcase committed Jul 29, 2009
@@ -0,0 +1,20 @@
+Copyright (c) 2009 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 README
@@ -0,0 +1,18 @@
+ConstantContact
+===============
+This is a very activeresource-like ruby wrapper to the constant contact api. It's not quite done yet and if you are interested in using this code, check it out, and message me with questions.
+
+
+
+Example
+=======
+
+ConstantContact::List.find(1)
+ConstantContact::List.find :all
+
+
+
+
+
+
+Copyright (c) 2009 Timothy Case, released under the MIT license
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the constant_contact plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the constant_contact plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'ConstantContact'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
@@ -0,0 +1,6 @@
+require 'constant_contact'
+
+ConstantContact::Base.api_key = ENV['CONSTANT_CONTACT_API_KEY']
+ConstantContact::Base.user = ENV['CONSTANT_CONTACT_USER']
+ConstantContact::Base.password = ENV['CONSTANT_CONTACT_PASSWORD']
+
@@ -0,0 +1 @@
+# Install hook code here
@@ -0,0 +1,12 @@
+directory = File.expand_path(File.dirname(__FILE__))
+
+require 'active_resource'
+require 'action_pack'
+require File.join(directory, 'constant_contact', 'formats')
+require File.join(directory, 'constant_contact', 'base')
+require File.join(directory, 'constant_contact', 'list');
+require File.join(directory, 'constant_contact', 'member')
+require File.join(directory, 'constant_contact', 'contact')
+require File.join(directory, 'constant_contact', 'campaign')
+require File.join(directory, 'constant_contact', 'contact_event')
+require File.join(directory, 'constant_contact', 'activity')
@@ -0,0 +1,35 @@
+
+module ConstantContact
+ class Activity < Base
+ self.format = ActiveResource::Formats::HtmlEncodedFormat
+ attr_accessor :contacts, :lists
+ def encode
+ post_data = "activityType=#{self.activity_type}"
+ post_data += self.encoded_data
+ post_data += self.encoded_lists
+ return post_data
+ end
+
+ protected
+ def encoded_data
+ result = "&data="
+ result += CGI.escape("Email Address,First Name,Last Name\n")
+ contact_strings = []
+ self.contacts.each do |contact|
+ contact_strings << "#{contact.email_address}, #{contact.first_name}, #{contact.last_name}"
+ end
+ result += CGI.escape(contact_strings.join("\n"))
+ return result
+ end
+
+ def encoded_lists
+ result = ""
+ self.lists.each do |list|
+ result += "&lists="
+ result += CGI.escape(list.id)
+ end
+ return result
+ end
+
+ end
+end
@@ -0,0 +1,60 @@
+
+module ConstantContact
+ class Base < ActiveResource::Base
+ self.site = "https://api.constantcontact.com"
+ self.format = :atom
+ class << self
+
+
+ def api_key
+ if defined?(@api_key)
+ @api_key
+ elsif superclass != Object && superclass.api_key
+ superclass.api_key.dup.freeze
+ end
+ end
+
+ def api_key=(api_key)
+ @connection = nil
+ @api_key = api_key
+ end
+
+ def connection(refresh = false)
+ if defined?(@connection) || superclass == Object
+ @connection = ActiveResource::Connection.new(site, format) if refresh || @connection.nil?
+ @connection.user = "#{api_key}%#{user}" if user
+ @connection.password = password if password
+ @connection.timeout = timeout if timeout
+ @connection
+ else
+ superclass.connection
+ end
+ end
+
+ def collection_path(prefix_options = {}, query_options = nil)
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
+ "/ws/customers/#{self.user}#{prefix(prefix_options)}#{collection_name}"
+ end
+
+ def element_path(id, prefix_options = {}, query_options = nil)
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
+ "#{collection_path}/#{id}"
+ end
+ end
+
+ def encode
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\">
+ <title type=\"text\"> </title>
+ <updated>2008-07-23T14:21:06.407Z</updated>
+ <author>Bluesteel</author>
+ <id>data:,none</id>
+ <summary type=\"text\">Bluesteel</summary>
+ <content type=\"application/vnd.ctct+xml\">
+ #{self.to_xml}
+ </content>
+ </entry>"
+ end
+
+
+ end
+end
@@ -0,0 +1,4 @@
+module ConstantContact
+ class Campaign < Base
+ end
+end
@@ -0,0 +1,27 @@
+module ConstantContact
+ class Contact < Base
+ attr_accessor :opt_in_source
+
+ def to_xml
+ xml = Builder::XmlMarkup.new
+ xml.tag!("Contact", :xmlns => "http://ws.constantcontact.com/ns/1.0/") do
+ self.attributes.each{|k, v| xml.tag!(k.camelize, v)}
+ xml.tag!("OptInSource", self.opt_in_source)
+ xml.tag!("ContactLists") do
+ xml.tag!("ContactList", :id=> self.list_url)
+ end
+ end
+ end
+
+ def opt_in_source
+ @opt_in_source ||= "ACTION_BY_CUSTOMER"
+ end
+
+ def list_url
+ id = defined?(self.list_id) ? self.list_id : 1
+ "http://api.constantcontact.com/ws/customers/#{self.class.user}/lists/#{id}"
+ end
+
+
+ end
+end
@@ -0,0 +1,7 @@
+module ConstantContact
+ class ContactEvent < Base
+ self.site += "/contacts/:contact_id"
+ end
+end
+
+
@@ -0,0 +1,2 @@
+require 'constant_contact/formats/atom_format'
+require 'constant_contact/formats/html_encoded_format'
@@ -0,0 +1,77 @@
+module ActiveResource
+ module Formats
+ module AtomFormat
+ extend self
+
+ def extension
+ "atom"
+ end
+
+ def mime_type
+ "application/atom+xml"
+ end
+
+ def encode(hash, options={})
+ hash.to_xml(options)
+ end
+
+ def decode(xml)
+ return [] if no_content?(xml)
+ result = Hash.from_xml(from_atom_data(xml))
+ is_collection?(xml) ? result['records'] : result.values.first
+ end
+
+
+ private
+
+ def from_atom_data(xml)
+ if is_collection?(xml)
+ return content_from_collection(xml)
+ else
+ return content_from_single_record(xml)
+ end
+ end
+
+ def no_content?(xml)
+ doc = REXML::Document.new(xml)
+ REXML::XPath.match(doc,'//content').size == 0
+ end
+
+ def is_collection?(xml)
+ doc = REXML::Document.new(xml)
+ REXML::XPath.match(doc,'//content').size > 1
+ end
+
+ def content_from_single_record(xml)
+ doc = REXML::Document.new(xml)
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ REXML::XPath.each(doc, '//content') do |e|
+ content = e.children[1]
+ str << content.to_s
+ end
+ str
+ end
+
+ def content_from_collection(xml)
+ doc = REXML::Document.new(xml)
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><records type=\"array\">"
+ REXML::XPath.each(doc, '//content') do |e|
+ content = e.children[1]
+ str << content.to_s
+ end
+ str << "</records>"
+ str
+ end
+
+ def content_from_member(xml)
+ doc = REXML::Document.new(xml)
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ REXML::XPath.each(doc, '//content') do |e|
+ content = e.children[1].children
+ str << content.to_s
+ end
+ str
+ end
+ end
+ end
+end
@@ -0,0 +1,10 @@
+module ActiveResource
+ module Formats
+ module HtmlEncodedFormat
+ extend self
+ def mime_type
+ "application/atom+xml"
+ end
+ end
+ end
+end
@@ -0,0 +1,4 @@
+module ConstantContact
+ class List < Base
+ end
+end
@@ -0,0 +1,7 @@
+module ConstantContact
+ class Member < Base
+ self.site += "/lists/:list_id"
+ end
+end
+
+
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :constant_contact do
+# # Task goes here
+# end
@@ -0,0 +1,40 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class Activity < Test::Unit::TestCase
+
+ context 'encode' do
+ setup do
+ @contacts = []
+ 3.times do |n|
+ @contacts << ConstantContact::Contact.new(:first_name => "Fred#{n}",
+ :last_name => "Test#{n}",
+ :email_address => "email#{n}@gmail.com")
+ end
+ @activity = ConstantContact::Activity.new(:activity_type => "SV_ADD")
+ @activity.contacts = @contacts
+ list = ConstantContact::List.new
+ list.stubs(:id).returns('http://api.constantcontact.com/ws/customers/joesflowers/lists/2')
+ @activity.lists = [list]
+ end
+
+ should 'include activity type' do
+ assert_match(/activityType=SV_ADD/, @activity.encode)
+ end
+
+ should 'include contacts data' do
+ assert_match(/\&data\=Email\+Address\%2CFirst\+Name\%2CLast\+Name\%0A/, @activity.encode)
+ assert_match(/email0\%40gmail\.com\%2C\+Fred0\%2C\+Test0\%0A/, @activity.encode)
+ end
+
+ should 'include lists' do
+ assert_match(/Test2\&lists\=http\%3A\%2F\%2Fapi\.constantcontact\.com\%2Fws\%2Fcustomers\%2Fjoesflowers\%2Flists\%2F2/, @activity.encode)
+ end
+ end
+
+ context 'format' do
+ should 'be html encoded' do
+ assert_equal ActiveResource::Formats[:html_encoded], ConstantContact::Activity.connection.format
+ end
+ end
+
+end
Oops, something went wrong.

0 comments on commit 3588790

Please sign in to comment.