shellpress 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "thor", ">= 0.14.6"
4
+ gem "mysql", "~> 2.8.1"
5
+
6
+ group :development do
7
+ gem "shoulda", ">= 0"
8
+ gem "bundler", "~> 1.0.0"
9
+ gem "jeweler", "~> 1.6.4"
10
+ gem "rcov", ">= 0"
11
+ end
@@ -0,0 +1,24 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.4)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ mysql (2.8.1)
10
+ rake (0.9.2)
11
+ rcov (0.9.9)
12
+ shoulda (2.11.3)
13
+ thor (0.14.6)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ bundler (~> 1.0.0)
20
+ jeweler (~> 1.6.4)
21
+ mysql (~> 2.8.1)
22
+ rcov
23
+ shoulda
24
+ thor (>= 0.14.6)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Scott Walkinshaw
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,163 @@
1
+ # shellpress
2
+
3
+ Manage WordPress from the command-line.
4
+
5
+ ## Commands
6
+
7
+ Shellpress comes with a variety of different commands that help you efficiently manage your WordPress installations. Try one of the following commands:
8
+
9
+ ### WordPress
10
+
11
+ Command: wordpress download
12
+
13
+ $ shellpress wordpress download # download and unpack WordPress
14
+
15
+ Options:
16
+ -v, [--version=VERSION] # Version of WordPress to download. Any version found in the release archive with a tar.gz link is valid (http://wordpress.org/download/release-archive/).
17
+
18
+ Description:
19
+ Downloads WordPress from the official site. By default, the latest stable version will be downloaded. The downloaded archive will be unpacked and the working directory will become the WordPress root directory. Use --version to specify a version to download.
20
+
21
+ Command: wordpress install
22
+
23
+ $ shellpress wordpress install # download and install WordPress
24
+
25
+ Options:
26
+ -c, [--config=CONFIG] # Loads settings from config file specified. Config must be in YAML format.
27
+ -s, [--skip-config] # If a config.yml file is found in the working directory, it will automatically be used unless you specify this flag.
28
+ -o, [--output=OUTPUT] # Writes a config file with the settings you chose during install.
29
+
30
+ Description:
31
+ Installs and downloads WordPress using the working directory as the WordPress root. If the "wp-content" folder already exists, it's assumed that WordPress has already been downloaded so only the install occurs. By default, this command will prompt you to enter the needed settings. Use --config (-c) [file] to specify a YAML config file. To save your settings into a config for future use, use --output (-o) [file] to write a YAML file. Before using this command, the WordPress root needs to be accessible via a URL and a MySQL database needs to exist with a valid user to access it.
32
+
33
+ Command: wordpress clean
34
+
35
+ $ shellpress wordpress clean
36
+
37
+ Options:
38
+ [--aliases-aallfalsedescDelete everything including *.yml files=ALIASES-AALLFALSEDESCDELETE EVERYTHING INCLUDING *.YML FILES]
39
+
40
+ Description:
41
+ Cleans up the working directory by deleting everything in it. By default, this excludes any *.yml config files. To delete everything including *.yml files, use --all (a).
42
+
43
+ ### Plugins
44
+
45
+ Command: plugin install
46
+
47
+ $ shellpress plugin install PLUGIN # install plugin
48
+
49
+ Options:
50
+ -v, [--version=VERSION] # Version of the plugin to install. Valid versions can be found on the plugin download page (http://wordpress.org/extend/plugins/[plugin]/download/) or in the SVN repository (http://plugins.svn.wordpress.org/[plugin]/tags/)
51
+
52
+ Description:
53
+ [PLUGIN] can either be a URL or a plugin name. If a plugin name is supplied, it will be downloaded from the WordPress Plugin Directory
54
+ (http://wordpress.org/extend/plugins/). If [PLUGIN] is a URL, it needs to be a ZIP file that contains either a directory or a single php file.
55
+
56
+ Command: plugin activate
57
+
58
+ $ shellpress plugin activate NAME # activate plugin
59
+
60
+ Description:
61
+ Activates a plugin from the default plugin directory (wp-content/plugins/). [NAME] is either the name of the directory, or the plugin file without ".php"
62
+
63
+ Command: plugin deactivate
64
+
65
+ $ shellpress plugin deactivate NAME # deactivate plugin
66
+
67
+ Description:
68
+ Deactivates a plugin from the default plugin directory (wp-content/plugins/). [NAME] is either the name of the directory, or the plugin file without ".php"
69
+
70
+ Command: plugin delete
71
+
72
+ $ shellpress plugin delete NAME # delete plugin
73
+
74
+ Description:
75
+ Deletes a plugin from the default plugin directory (wp-content/plugins/). [NAME] is either the name of the directory, or the plugin file without ".php"
76
+
77
+ Command: plugin download
78
+
79
+ $ shellpress plugin download URL # downloads plugin from URL
80
+
81
+ Description:
82
+ Downloads and extracts a plugin to the default plugin directory (wp-content/plugins/). [URL] must be a ZIP archive. The downloaded ZIP file will be deleted after it's
83
+ expanded.
84
+
85
+ ### Themes
86
+
87
+ Command: theme install
88
+
89
+ $ shellpress theme install THEME # [THEME] can either be a URL or a theme name. If a theme name is supplied, it will be downloaded from the WordPress Theme Directory
90
+
91
+ Options:
92
+ -v, [--version=VERSION] # Version of the theme to install. Valid version numbers can be found in the theme's SVN repository (http://themes.svn.wordpress.org/[theme]/)
93
+
94
+ Description:
95
+ [THEME] can either be a URL or a theme name. If a theme name is supplied, it will be downloaded from the WordPress Theme Directory
96
+ (http://wordpress.org/extend/themes/). If [THEME] is a URL, it needs to be a ZIP file that contains a directory.
97
+
98
+ Command: theme delete
99
+
100
+ $ shellpress theme delete NAME # removes theme
101
+
102
+ Options:
103
+ -f, [--force] # Force delete theme without confirmation
104
+
105
+ Description:
106
+ Deletes a theme. [NAME] is the name of the theme directory in wp-content/themes/.
107
+
108
+ Command: theme switch
109
+
110
+ $ shellpress theme switch NAME # switches from the current theme to new theme
111
+
112
+ Description:
113
+ Switches (activates) to [NAME] theme. [NAME] is the theme directory name in wp-content/themes/. Child themes are also supported.
114
+
115
+ Command: theme download
116
+
117
+ $ shellpress theme download URL # downloads theme from URL
118
+
119
+ Description:
120
+ Downloads a theme from the URL provided. URL needs be a ZIP file that contains 1 directory. ZIP will be expanded and deleted. The theme will be moved to
121
+ wp-content/themes/.
122
+
123
+ ### Users
124
+
125
+ Command: user add
126
+
127
+ $ shellpress user add [USER]
128
+
129
+ Options:
130
+ -u, [--url=URL] # User's URL
131
+ -r, [--role=ROLE] # User role. Valid roles and descriptions can be found here (http://codex.wordpress.org/Roles_and_Capabilities).
132
+ -p, [--password=PASSWORD] # User's password
133
+ -f, [--first-name=FIRST_NAME] # User's first name
134
+ -e, [--email=EMAIL] # User's email address. Their account info will be emailed here.
135
+ -l, [--last-name=LAST_NAME] # User's last name
136
+ -s, [--ssl=SSL] # Force SSL
137
+ # Default: 0
138
+
139
+ Description:
140
+ Creates a new WordPress user account. Do not try using this for existing users.
141
+
142
+
143
+ ### Database
144
+
145
+ Command: database reset
146
+
147
+ $ shellpress database reset
148
+
149
+ Options:
150
+ -e, [--exclude-users] # Excludes wp_usermeta and wp_users from being cleared
151
+
152
+ Description:
153
+ Empties all WordPress tables by truncating. By default, all tables will be cleared. To preserve the user tables, use --exclude_users (-e)
154
+
155
+ ## Config
156
+
157
+ See `config.yml.sample` for an example of an installation config.yml.
158
+
159
+ Usage: `shellpress wordpress install -c config.yml`
160
+
161
+ ## Copyright
162
+
163
+ Copyright (c) 2011 Scott Walkinshaw. See LICENSE for further details.
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "shellpress"
18
+ gem.homepage = "http://github.com/swalkinshaw/shellpress"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Manage WordPress from the command line}
21
+ gem.description = %Q{shellpress is a command line WordPress manager. It provides commands for common WordPress administration actions and lets you easily script them}
22
+ gem.email = "scott.walkinshaw@gmail.com"
23
+ gem.authors = ["Scott Walkinshaw"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "shellpress #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+ require "shellpress"
5
+ Shellpress::CLI.start
@@ -0,0 +1,12 @@
1
+ ---
2
+ mysql:
3
+ pass: password
4
+ db: wp_db
5
+ host: localhost
6
+ user: wp_user
7
+ wp:
8
+ title: Blog Title
9
+ url: blog.example.com
10
+ pass: password
11
+ user: admin
12
+ email: email@example.com
@@ -0,0 +1,13 @@
1
+ require "rubygems"
2
+ require "thor"
3
+
4
+ module Shellpress; end
5
+
6
+ require "shellpress/thor"
7
+ require "shellpress/database"
8
+ require "shellpress/plugin"
9
+ require "shellpress/post"
10
+ require "shellpress/theme"
11
+ require "shellpress/user"
12
+ require "shellpress/wordpress"
13
+ require "shellpress/cli"
@@ -0,0 +1,64 @@
1
+ class Shellpress::CLI < Shellpress::Thor
2
+ no_tasks do
3
+ def constantize(s)
4
+ Shellpress.constants.each { |k| return Shellpress.const_get(k) if k.to_s.downcase == s }
5
+ nil
6
+ end
7
+
8
+ def prefix(s)
9
+ s.to_s.downcase.gsub(/::.+/, "")
10
+ end
11
+
12
+ def suffix(s)
13
+ s.to_s.gsub(/.+?::/, "")
14
+ end
15
+
16
+ def print_table_for_class(klass)
17
+ pref = prefix(self.class)
18
+ say "#{suffix(klass)} commands:"
19
+ tasks = klass.printable_tasks.reject { |task| task[0] =~ /^#{pref} #{suffix(klass).downcase} help/ }
20
+ print_table(tasks, :ident => 2)
21
+ say
22
+ end
23
+ end
24
+
25
+ desc "plugin", "Commands related to plugins."
26
+ subcommand "plugin", Shellpress::Plugin
27
+
28
+ desc "theme", "Commands related to themes."
29
+ subcommand "theme", Shellpress::Theme
30
+
31
+ desc "user", "Commands related to users."
32
+ subcommand "user", Shellpress::User
33
+
34
+ desc "wordpress", "Commands related to wordpress."
35
+ subcommand "wordpress", Shellpress::Wordpress
36
+
37
+ desc "database", "Commands related to the database."
38
+ subcommand "database", Shellpress::Database
39
+
40
+ desc "post", "Commands related to posts."
41
+ subcommand "post", Shellpress::Post
42
+
43
+ def help(*commands)
44
+ if commands.empty?
45
+ # Case 1:
46
+ # Either `shellpress help' or `shellpress' called. Print out help for all commands.
47
+ ks = Shellpress.constants.map { |k| Shellpress.const_get(k) }
48
+ ks = ks.sort_by { |k| k::ORDER }
49
+ # Don't call help on CLI or infinite recursion occurs
50
+ ks.reject { |k| self.class == k || k == Shellpress::Thor }.each do |klass|
51
+ print_table_for_class(klass)
52
+ end
53
+ say "Use `#{prefix(self.class)} help [COMMAND] [SUBCOMMAND]' to learn more."
54
+ else
55
+ cmd = commands[0]
56
+ klass = constantize(cmd)
57
+ unless klass
58
+ say "Unknown command `#{cmd}'."
59
+ else
60
+ klass.new.help(*commands[1..-1])
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,32 @@
1
+ require "mysql"
2
+
3
+ class Shellpress::Database < Shellpress::Thor
4
+ ORDER = 3
5
+ desc "reset", "resets by emptying all WordPress tables"
6
+ long_desc <<-DESC
7
+ Empties all WordPress tables by truncating. By default, all tables will be cleared.
8
+ To preserve the user tables, use --exclude-users (-e)
9
+ DESC
10
+ method_option :exclude_users, :type => :boolean, :aliases => %w(-e),
11
+ :desc => "Excludes wp_usermeta and wp_users tables from being cleared"
12
+ def reset
13
+
14
+ tables = %w(wp_commentmeta wp_comments wp_links wp_options wp_postmeta wp_posts wp_terms wp_term_relationships wp_term_taxonomy)
15
+ if options[:exclude_users]
16
+ tables += %w(wp_usermeta wp_users)
17
+ end
18
+
19
+ # doesnt work yet since there's no way to retrieve config settings
20
+ begin
21
+ #wp = Mysql.real_connect(mysql['host'], mysql['user'], mysql['pass'])
22
+ #tables.each do |t|
23
+ # wp.query("TRUNCATE TABLE #{t}")
24
+ #end
25
+ rescue Mysql::Error => e
26
+ abort e
27
+ ensure
28
+ wp.close if wp
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,135 @@
1
+ require "uri"
2
+ require "open-uri"
3
+
4
+ class Shellpress::Plugin < Shellpress::Thor
5
+ ORDER = 0
6
+ include Thor::Actions
7
+
8
+ desc "install PLUGIN", "install plugin"
9
+ long_desc <<-DESC
10
+ [PLUGIN] can either be a URL or a plugin name. If a plugin name is supplied, it will be downloaded from the WordPress Plugin Directory (http://wordpress.org/extend/plugins/).
11
+ If [PLUGIN] is a URL, it needs to be a ZIP file that contains either a directory or a single php file.
12
+ DESC
13
+ method_option :version, :type => :string, :aliases => %w(-v),
14
+ :desc => "Version of the plugin to install. Valid versions can be found on the plugin download page (http://wordpress.org/extend/plugins/[plugin]/download/) or in the SVN repository (http://plugins.svn.wordpress.org/[plugin]/tags/)"
15
+ def install(plugin)
16
+ version = options[:version]
17
+
18
+ if plugin =~ URI::regexp
19
+ invoke :download, [plugin]
20
+ filename = File.basename(URI.parse(plugin).path)
21
+ name = filename.split(".").first
22
+ invoke :activate, [name]
23
+ else
24
+ if version
25
+ begin
26
+ response = open("http://svn.wp-plugins.org/#{plugin}/tags/#{version}/readme.txt")
27
+ url = "http://downloads.wordpress.org/plugin/#{plugin}.#{version}.zip"
28
+ rescue
29
+ abort "Error: Invalid plugin #{plugin}"
30
+ end
31
+ else
32
+ begin
33
+ response = open("http://svn.wp-plugins.org/#{plugin}/trunk/readme.txt").read
34
+ stable = response.match(/Stable tag: (.*)\n/)[1]
35
+ if stable == "trunk"
36
+ url = "http://downloads.wordpress.org/plugin/#{plugin}.zip"
37
+ elsif stable =~ /[\d\.]+/
38
+ url = "http://downloads.wordpress.org/plugin/#{plugin}.#{stable}.zip"
39
+ else
40
+ abort "Error: Invalid plugin #{plugin} or invalid readme.txt"
41
+ end
42
+ rescue
43
+ abort "Error: Invalid plugin #{plugin}"
44
+ end
45
+ end
46
+ invoke :download, [url]
47
+ invoke :activate, [plugin]
48
+ end
49
+ end
50
+
51
+ desc "download URL", "downloads plugin from URL"
52
+ long_desc <<-DESC
53
+ Downloads and extracts a plugin to the default plugin directory (wp-content/plugins/). [URL] must be a ZIP archive.
54
+ The downloaded ZIP file will be deleted after it's expanded.
55
+ DESC
56
+ def download(url)
57
+ zip = File.basename(URI.parse(url).path)
58
+ plugin = zip.split(".").first
59
+ run "wget #{url}", :verbose => false
60
+ run "unzip #{zip}", :verbose => false
61
+ remove_file "#{zip}", :verbose => false
62
+ run "mv #{plugin} wp-content/plugins/"
63
+ end
64
+
65
+ desc "activate NAME", "activate plugin"
66
+ long_desc <<-DESC
67
+ Activates a plugin from the default plugin directory (wp-content/plugins/).
68
+ [NAME] is either the name of the directory, or the plugin file without ".php"
69
+ DESC
70
+ method_option :network_wide, :type => :boolean, :aliases => %w(-n),
71
+ :desc => "Activates the plugin network wide. Only applies for WordPress Network installs."
72
+ def activate(name)
73
+ network = options[:network_wide]
74
+ base = "wp-content/plugins"
75
+ php = "php -r \"include 'wp-load.php';"
76
+ php << "require_once(ABSPATH . 'wp-admin/includes/plugin.php');"
77
+ if File.exists?("#{base}/#{name}/#{name}.php")
78
+ if network
79
+ php << "activate_plugin('#{name}/#{name}.php', '', true);\""
80
+ else
81
+ php << "activate_plugin('#{name}/#{name}.php');\""
82
+ end
83
+ elsif File.exists?("#{base}/#{name}.php")
84
+ if network
85
+ php << "activate_plugin('#{name}.php', '', true);\""
86
+ else
87
+ php << "activate_plugin('#{name}.php');\""
88
+ end
89
+ else
90
+ abort "Error: Invalid plugin #{name}"
91
+ end
92
+ run php
93
+ end
94
+
95
+ desc "delete NAME", "delete plugin"
96
+ long_desc <<-DESC
97
+ Deletes a plugin from the default plugin directory (wp-content/plugins/).
98
+ [NAME] is either the name of the directory, or the plugin file without ".php"
99
+ DESC
100
+ def delete(name)
101
+ base = "wp-content/plugins"
102
+ php = "php -r \"include 'wp-load.php';"
103
+ php << "require_once(ABSPATH . 'wp-admin/includes/plugin.php');"
104
+ php << "require_once(ABSPATH . 'wp-admin/includes/file.php');"
105
+ if File.exists?("#{base}/#{name}/#{name}.php")
106
+ php << "delete_plugins(array('#{name}/#{name}.php'));\""
107
+ elsif File.exists?("#{base}/#{name}.php")
108
+ php << "delete_plugins(array('#{name}.php'));\""
109
+ else
110
+ abort "Error: Invalid plugin #{name}"
111
+ end
112
+ run php
113
+ end
114
+
115
+ desc "deactivate NAME", "deactivate plugin"
116
+ long_desc <<-DESC
117
+ Deactivates a plugin from the default plugin directory (wp-content/plugins/).
118
+ [NAME] is either the name of the directory, or the plugin file without ".php"
119
+ Note: Plugin will be deactivated network wide if applicable.
120
+ DESC
121
+ def deactivate(name)
122
+ base = "wp-content/plugins"
123
+ php = "php -r \"include 'wp-load.php';"
124
+ php << "require_once(ABSPATH . 'wp-admin/includes/plugin.php');"
125
+ php << "require_once(ABSPATH . 'wp-admin/includes/file.php');"
126
+ if File.exists?("#{base}/#{name}/#{name}.php")
127
+ php << "deactivate_plugins(array('#{name}/#{name}.php'));\""
128
+ elsif File.exists?("#{base}/#{name}.php")
129
+ php << "deactivate_plugins(array('#{name}.php'));\""
130
+ else
131
+ abort "Error: Invalid plugin #{name}"
132
+ end
133
+ run php
134
+ end
135
+ end
@@ -0,0 +1,31 @@
1
+ class Shellpress::Post < Shellpress::Thor
2
+ ORDER = 2
3
+ include Thor::Actions
4
+
5
+ desc "delete [POST_ID/SLUG]", "deletes a post, attachment, or page of the specified ID or path (slug)"
6
+ method_option :force, :type => :boolean, :aliases => %w(-f), :default => true,
7
+ :desc => "Force delete post bypassing the Trash"
8
+ method_option :type, :type => :string, :aliases => %w(-t), :default => "post",
9
+ :desc => "The type of object to delete. Default valid types: post, page, attachment, revision, nav_menu. Custom post types are also supported"
10
+ def delete(id)
11
+ force = options[:force]
12
+ type = options[:type]
13
+
14
+ php = "<?php include 'wp-load.php';"
15
+
16
+ if id =~ /\d+/
17
+ php << "wp_delete_post(#{id}, #{force});"
18
+ else
19
+ php << "$post = get_page_by_path('#{id}', OBJECT, '#{type}');"
20
+ php << "if ($post) wp_delete_post($post->ID, #{force});"
21
+ end
22
+
23
+ php << "?>"
24
+
25
+ File.open("temp.php", "w") {|f| f.write(php)}
26
+ run "php -q temp.php"
27
+ remove_file "temp.php", :verbose => false
28
+
29
+ end
30
+ end
31
+
@@ -0,0 +1,105 @@
1
+ require "uri"
2
+ require "open-uri"
3
+ require "fileutils"
4
+
5
+ class Shellpress::Theme < Shellpress::Thor
6
+ ORDER = 1
7
+ include Thor::Actions
8
+
9
+ desc "switch NAME", "switches from the current theme to new theme"
10
+ long_desc <<-DESC
11
+ Switches (activates) to [NAME] theme. [NAME] is the theme directory name in wp-content/themes/.
12
+ Child themes are also supported.
13
+ DESC
14
+ def switch(theme)
15
+ base = "wp-content/themes/#{theme}"
16
+
17
+ if !File.exists?(base)
18
+ abort "Error: Invalid theme #{theme}"
19
+ end
20
+
21
+ path = File.join(base, "style.css")
22
+ file = File.open(path, "rb").read
23
+ if file =~ /Template: (.*)\n/
24
+ parent = $1
25
+ end
26
+ php = "php -r \"include 'wp-load.php';"
27
+ if parent
28
+ php << "switch_theme('#{parent}', '#{theme}');\""
29
+ else
30
+ php << "switch_theme('#{theme}', '#{theme}');\""
31
+ end
32
+ run php
33
+ end
34
+
35
+ desc "install THEME", "download and installs a WordPress theme"
36
+ long_desc <<-DESC
37
+ [THEME] can either be a URL or a theme name. If a theme name is supplied, it will be downloaded from the WordPress Theme Directory (http://wordpress.org/extend/themes/).
38
+ If [THEME] is a URL, it needs to be a ZIP file that contains a directory.
39
+ DESC
40
+ method_option :version, :type => :string, :aliases => %w(-v),
41
+ :desc => "Version of the theme to install. Valid version numbers can be found in the theme's SVN repository (http://themes.svn.wordpress.org/[theme]/)"
42
+ def install(theme)
43
+ version = options[:version]
44
+
45
+ if theme =~ URI::regexp
46
+ invoke :download, [theme]
47
+ filename = File.basename(URI.parse(theme).path)
48
+ name = filename.split(".").first
49
+ invoke :switch, [name]
50
+ else
51
+ if version
52
+ url = "http://wordpress.org/extend/themes/download/#{theme}.#{version}.zip"
53
+ else
54
+ begin
55
+ response = open("http://themes.svn.wordpress.org/#{theme}/").read
56
+ version = response.match(%r|<a href="([\d+.]+)/">(.*)/</a></li>\n </ul>|)[1]
57
+ url = "http://wordpress.org/extend/themes/download/#{theme}.#{version}.zip"
58
+ rescue
59
+ abort "Error: Invalid theme #{theme}"
60
+ end
61
+ end
62
+ invoke :download, [url]
63
+ invoke :switch, [theme]
64
+ end
65
+ end
66
+
67
+ desc "download URL", "downloads theme from URL"
68
+ long_desc <<-DESC
69
+ Downloads a theme from the URL provided. URL needs be a ZIP file that contains 1 directory.
70
+ ZIP will be expanded and deleted. The theme will be moved to wp-content/themes/.
71
+ DESC
72
+ def download(url)
73
+ zip = File.basename(URI.parse(url).path)
74
+ theme = zip.split(".").first
75
+ run "wget #{url}", :verbose => false
76
+ run "unzip #{zip}", :verbose => false
77
+ remove_file "#{zip}", :verbose => false
78
+ run "mv #{theme} wp-content/themes/"
79
+ end
80
+
81
+ desc "delete NAME", "removes theme"
82
+ long_desc <<-DESC
83
+ Deletes a theme. [NAME] is the name of the theme directory in wp-content/themes/.
84
+ DESC
85
+ method_option :force, :type => :boolean, :aliases => %w(-f),
86
+ :desc => "Force delete theme without confirmation"
87
+ def delete(theme)
88
+ path = "wp-content/themes/#{theme}"
89
+
90
+ if !File.exists?(path)
91
+ abort "Error: Invalid theme #{theme}"
92
+ end
93
+
94
+ force = options[:force]
95
+ if force
96
+ FileUtils.rm_rf path
97
+ else
98
+ confirm = ask "Delete #{path}? [Yn]"
99
+ if confirm == "Y"
100
+ FileUtils.rm_rf path
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -0,0 +1,33 @@
1
+ class Shellpress::Thor < Thor
2
+ ORDER = -1
3
+
4
+ def self.banner(task, namespace = nil, subcommand = false)
5
+ "#{basename} #{self.to_s.gsub(/Shellpress::/, "").downcase} #{task.formatted_usage(self, $thor_runner, subcommand)}"
6
+ end
7
+
8
+ no_tasks do
9
+ def prefix(s)
10
+ s.to_s.gsub(/::.+/, "")
11
+ end
12
+
13
+ def suffix(s)
14
+ s.to_s.gsub(/.+?::/, "")
15
+ end
16
+ end
17
+
18
+ def help(*cmds)
19
+ klass = self.class
20
+ pref = prefix(klass).downcase
21
+
22
+ if cmds[0]
23
+ # Subcommand
24
+ super(*cmds)
25
+ else
26
+ say "#{suffix(klass)} commands:"
27
+ tasks = klass.printable_tasks.reject { |task| task[0] =~ /^#{pref} #{suffix(klass).downcase} help/ }
28
+ print_table(tasks, :ident => 2)
29
+ end
30
+
31
+ say
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ require "tempfile"
2
+
3
+ class Shellpress::User < Shellpress::Thor
4
+ ORDER = 4
5
+ desc "add [USER]", "creates a new WordPress user"
6
+ long_desc <<-DESC
7
+ Creates a new WordPress user account. Do not try using this for existing users.
8
+ DESC
9
+ method_option :role, :type => :string, :aliases => %w(-r),
10
+ :desc => "User role. Valid roles and descriptions can be found here (http://codex.wordpress.org/Roles_and_Capabilities)."
11
+ method_option :email, :type => :string, :aliases => %w(-e),
12
+ :desc => "User's email address. Their account info will be emailed here."
13
+ method_option :url, :type => :string, :aliases => %w(-u),
14
+ :desc => "User's URL"
15
+ method_option :first_name, :type => :string, :aliases => %w(-f),
16
+ :desc => "User's first name"
17
+ method_option :last_name, :type => :string, :aliases => %w(-l),
18
+ :desc => "User's last name"
19
+ method_option :ssl, :type => :string, :aliases => %w(-s), :default => '0',
20
+ :desc => "Force SSL"
21
+ method_option :password, :type => :string, :aliases => %w(-p),
22
+ :desc => "User's password"
23
+ def add(user)
24
+ php = <<-PHP
25
+ <?php
26
+ include 'wp-load.php';
27
+ require_once( ABSPATH . WPINC . '/registration.php');
28
+ if (!is_object(get_user_by('slug', '#{user}'))) {
29
+ wp_insert_user(array(
30
+ 'user_login' => '#{user}',
31
+ 'role' => '#{option[:role]}',
32
+ 'user_email' => '#{option[:email]}',
33
+ 'user_url' => '#{option[:url]}',
34
+ 'first_name' => '#{option[:first_name]}',
35
+ 'last_name' => '#{option[:last_name]}',
36
+ 'use_ssl' => '#{option[:ssl]}',
37
+ 'user_pass' => '#{option[:password]}'
38
+ ));
39
+ }
40
+ ?>
41
+ PHP
42
+
43
+ file = Tempfile.open(["useradd", ".php"])
44
+ begin
45
+ file.write(php)
46
+ run "php -q #{file.path}"
47
+ ensure
48
+ file.close
49
+ file.delete
50
+ end
51
+
52
+ end
53
+ end
54
+
@@ -0,0 +1,113 @@
1
+ require "yaml"
2
+
3
+ class Shellpress::Wordpress < Shellpress::Thor
4
+ ORDER = 5
5
+ include Thor::Actions
6
+
7
+ def self.source_root
8
+ File.dirname(__FILE__)
9
+ end
10
+
11
+ desc "download", "download and unpack WordPress"
12
+ long_desc <<-DESC
13
+ Downloads WordPress from the official site. By default, the latest stable version will be downloaded.
14
+ The downloaded archive will be unpacked and the working directory will become the WordPress root directory.
15
+ Use --version to specify a version to download.
16
+ DESC
17
+ method_option :version, :type => :string, :aliases => %w(-v),
18
+ :desc => "Version of WordPress to download. Any version found in the release archive with a tar.gz link is valid (http://wordpress.org/download/release-archive/)."
19
+ def download
20
+ version = options[:version]
21
+
22
+ if version
23
+ say "*** Downloading WordPress #{version}", :green
24
+ run "wget http://wordpress.org/wordpress-#{version}.tar.gz -O wordpress.tar.gz", :verbose => false
25
+ else
26
+ say "*** Downloading latest WordPress", :green
27
+ run "wget http://wordpress.org/latest.tar.gz -O wordpress.tar.gz", :verbose => false
28
+ end
29
+
30
+ run "tar zxf wordpress.tar.gz", :verbose => false
31
+ remove_file "wordpress.tar.gz", :verbose => false
32
+ run "mv wordpress/* .", :verbose => false
33
+ run "rmdir wordpress", :verbose => false
34
+ end
35
+
36
+ desc "install", "download and install WordPress"
37
+ long_desc <<-DESC
38
+ Installs and downloads WordPress using the working directory as the WordPress root.
39
+ If the "wp-content" folder already exists, it's assumed that WordPress has already been downloaded so only the install occurs.
40
+ By default, this command will prompt you to enter the needed settings. Use --config (-c) [file] to specify a YAML config file.
41
+ To save your settings into a config for future use, use --output (-o) [file] to write a YAML file.
42
+ Before using this command, the WordPress root needs to be accessible via a URL and a MySQL database needs to exist with a valid user to access it.
43
+ DESC
44
+ method_option :config, :type => :string, :aliases => %w(-c),
45
+ :desc => "Loads settings from config file specified. Config must be in YAML format."
46
+ method_option :skip_config, :type => :boolean, :aliases => %w(-s),
47
+ :desc => "If a config.yml file is found in the working directory, it will automatically be used unless you specify this flag."
48
+ method_option :output, :type => :string, :aliases => %w(-o),
49
+ :desc => "Writes a config file with the settings you chose during install."
50
+ def install
51
+ config = options[:config]
52
+ output = options[:output]
53
+
54
+ unless File.exists?("wp-content")
55
+ invoke :download
56
+ end
57
+
58
+ if config
59
+ say "*** Loading settings from #{config}", :green
60
+ settings = YAML.load_file(config)
61
+ elsif File.exists?("config.yml") && !options[:skip_config]
62
+ say "*** Loading settings from config.yml", :green
63
+ settings = YAML.load_file("config.yml")
64
+ else
65
+ settings = { "mysql" => {}, "wp" => {} }
66
+
67
+ settings["mysql"]["host"] = ask "MySQL host: "
68
+ settings["mysql"]["db"] = ask "MySQL db: "
69
+ settings["mysql"]["user"] = ask "MySQL user: "
70
+ settings["mysql"]["pass"] = ask "MySQL pass: "
71
+ settings["wp"]["title"]= ask "WordPress Title: "
72
+ settings["wp"]["user"] = ask "WordPress User: "
73
+ settings["wp"]["pass"] = ask "WordPress Pass: "
74
+ settings["wp"]["email"] = ask "WordPress Email: "
75
+ settings["wp"]["url"] = ask "WordPress URL: "
76
+
77
+ if output
78
+ File.open(output, "w") do |out|
79
+ say "*** #{output} written", :green
80
+ YAML.dump(settings, out)
81
+ end
82
+ end
83
+ end
84
+
85
+ say "*** Downloading WordPress Salt keys", :green
86
+ run "wget https://api.wordpress.org/secret-key/1.1/salt/ -O /tmp/wp.keys", :verbose => false
87
+
88
+ say "*** Updating wp-config with settings", :green
89
+ run "sed -e 's/localhost/#{settings['mysql']['host']}/' -e 's/database_name_here/#{settings['mysql']['db']}/' -e 's/username_here/#{settings['mysql']['user']}/' -e 's/password_here/#{settings['mysql']['pass']}/' wp-config-sample.php > wp-config.php", :verbose => false
90
+ run "sed -i '\/\#\@\-\/r \/tmp\/wp.keys' wp-config.php", :verbose => false
91
+ run "sed -i '\/\#\@\+\/,\/\#\@\-\/d' wp-config.php", :verbose => false
92
+
93
+ run "curl -d 'weblog_title=#{settings['wp']['title']}&user_name=#{settings['wp']['user']}&admin_password=#{settings['wp']['pass']}&admin_password2=#{settings['wp']['pass']}&admin_email=#{settings['wp']['email']}' http://#{settings['wp']['url']}/wp-admin/install.php?step=2"
94
+
95
+ end
96
+
97
+ desc "clean", "delete the contents of the working directory"
98
+ long_desc <<-DESC
99
+ Cleans up the working directory by deleting everything in it. By default, this excludes any *.yml config files.
100
+ To delete everything including *.yml files, use --all (a).
101
+ DESC
102
+ method_option :all => false, :aliases => %w(-a),
103
+ :desc => "Delete everything including *.yml files"
104
+ def clean
105
+ if options[:all]
106
+ FileUtils.rm_rf "."
107
+ else
108
+ Dir.glob("*").reject{|file| ['.yml'].include?(File.extname(file)) }
109
+ end
110
+ end
111
+
112
+ end
113
+
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{shellpress}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Scott Walkinshaw"]
12
+ s.date = %q{2011-08-04}
13
+ s.default_executable = %q{shellpress}
14
+ s.description = %q{shellpress is a command line WordPress manager. It provides commands for common WordPress administration actions and lets you easily script them}
15
+ s.email = %q{scott.walkinshaw@gmail.com}
16
+ s.executables = ["shellpress"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE",
25
+ "README.md",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "bin/shellpress",
29
+ "config.yml.sample",
30
+ "lib/shellpress.rb",
31
+ "lib/shellpress/cli.rb",
32
+ "lib/shellpress/database.rb",
33
+ "lib/shellpress/plugin.rb",
34
+ "lib/shellpress/post.rb",
35
+ "lib/shellpress/theme.rb",
36
+ "lib/shellpress/thor.rb",
37
+ "lib/shellpress/user.rb",
38
+ "lib/shellpress/wordpress.rb",
39
+ "shellpress.gemspec",
40
+ "test/helper.rb",
41
+ "test/test_shellpress.rb"
42
+ ]
43
+ s.homepage = %q{http://github.com/swalkinshaw/shellpress}
44
+ s.licenses = ["MIT"]
45
+ s.require_paths = ["lib"]
46
+ s.rubygems_version = %q{1.6.2}
47
+ s.summary = %q{Manage WordPress from the command line}
48
+
49
+ if s.respond_to? :specification_version then
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<thor>, [">= 0.14.6"])
54
+ s.add_runtime_dependency(%q<mysql>, ["~> 2.8.1"])
55
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
56
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
58
+ s.add_development_dependency(%q<rcov>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<thor>, [">= 0.14.6"])
61
+ s.add_dependency(%q<mysql>, ["~> 2.8.1"])
62
+ s.add_dependency(%q<shoulda>, [">= 0"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
65
+ s.add_dependency(%q<rcov>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<thor>, [">= 0.14.6"])
69
+ s.add_dependency(%q<mysql>, ["~> 2.8.1"])
70
+ s.add_dependency(%q<shoulda>, [">= 0"])
71
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
72
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
73
+ s.add_dependency(%q<rcov>, [">= 0"])
74
+ end
75
+ end
76
+
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'shellpress'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestShellpress < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shellpress
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Scott Walkinshaw
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-04 00:00:00 -06:00
19
+ default_executable: shellpress
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 43
29
+ segments:
30
+ - 0
31
+ - 14
32
+ - 6
33
+ version: 0.14.6
34
+ name: thor
35
+ version_requirements: *id001
36
+ prerelease: false
37
+ - !ruby/object:Gem::Dependency
38
+ type: :runtime
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 45
45
+ segments:
46
+ - 2
47
+ - 8
48
+ - 1
49
+ version: 2.8.1
50
+ name: mysql
51
+ version_requirements: *id002
52
+ prerelease: false
53
+ - !ruby/object:Gem::Dependency
54
+ type: :development
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ name: shoulda
65
+ version_requirements: *id003
66
+ prerelease: false
67
+ - !ruby/object:Gem::Dependency
68
+ type: :development
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ hash: 23
75
+ segments:
76
+ - 1
77
+ - 0
78
+ - 0
79
+ version: 1.0.0
80
+ name: bundler
81
+ version_requirements: *id004
82
+ prerelease: false
83
+ - !ruby/object:Gem::Dependency
84
+ type: :development
85
+ requirement: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ~>
89
+ - !ruby/object:Gem::Version
90
+ hash: 7
91
+ segments:
92
+ - 1
93
+ - 6
94
+ - 4
95
+ version: 1.6.4
96
+ name: jeweler
97
+ version_requirements: *id005
98
+ prerelease: false
99
+ - !ruby/object:Gem::Dependency
100
+ type: :development
101
+ requirement: &id006 !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ name: rcov
111
+ version_requirements: *id006
112
+ prerelease: false
113
+ description: shellpress is a command line WordPress manager. It provides commands for common WordPress administration actions and lets you easily script them
114
+ email: scott.walkinshaw@gmail.com
115
+ executables:
116
+ - shellpress
117
+ extensions: []
118
+
119
+ extra_rdoc_files:
120
+ - LICENSE
121
+ - README.md
122
+ files:
123
+ - Gemfile
124
+ - Gemfile.lock
125
+ - LICENSE
126
+ - README.md
127
+ - Rakefile
128
+ - VERSION
129
+ - bin/shellpress
130
+ - config.yml.sample
131
+ - lib/shellpress.rb
132
+ - lib/shellpress/cli.rb
133
+ - lib/shellpress/database.rb
134
+ - lib/shellpress/plugin.rb
135
+ - lib/shellpress/post.rb
136
+ - lib/shellpress/theme.rb
137
+ - lib/shellpress/thor.rb
138
+ - lib/shellpress/user.rb
139
+ - lib/shellpress/wordpress.rb
140
+ - shellpress.gemspec
141
+ - test/helper.rb
142
+ - test/test_shellpress.rb
143
+ has_rdoc: true
144
+ homepage: http://github.com/swalkinshaw/shellpress
145
+ licenses:
146
+ - MIT
147
+ post_install_message:
148
+ rdoc_options: []
149
+
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ hash: 3
158
+ segments:
159
+ - 0
160
+ version: "0"
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ none: false
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ hash: 3
167
+ segments:
168
+ - 0
169
+ version: "0"
170
+ requirements: []
171
+
172
+ rubyforge_project:
173
+ rubygems_version: 1.6.2
174
+ signing_key:
175
+ specification_version: 3
176
+ summary: Manage WordPress from the command line
177
+ test_files: []
178
+