diff --git a/3.1/modules/bitly/controllers/admin_bitly.php b/3.1/modules/bitly/controllers/admin_bitly.php new file mode 100644 index 00000000..ee7e9f6f --- /dev/null +++ b/3.1/modules/bitly/controllers/admin_bitly.php @@ -0,0 +1,91 @@ +validate()) { + $current_login = module::get_var("bitly", "login"); + $current_key = module::get_var("bitly", "api_key"); + $current_domain = module::get_var("bitly", "domain"); + $new_login = $form->configure_bitly->login->value; + $new_key = $form->configure_bitly->api_key->value; + $new_domain = $form->configure_bitly->domain->value; + + module::set_var("bitly", "login", $new_login); + module::set_var("bitly", "api_key", $new_key); + module::set_var("bitly", "domain", $new_domain); + + if (!bitly::check_config()) { + url::redirect("admin/bitly"); + } else { + if ($current_login && !$new_login) { + message::success(t("Your bit.ly login has been cleared.")); + } else if ($current_login && $new_login && $current_login != $new_login) { + message::success(t("Your bit.ly login has been changed.")); + } else if (!$current_login && $new_login) { + message::success(t("Your bit.ly login has been saved.")); + } + if ($current_key && !$new_key) { + message::success(t("Your bit.ly API key has been cleared.")); + } else if ($current_key && $new_key && $current_key != $new_key) { + message::success(t("Your bit.ly API key has been changed.")); + } else if (!$current_key && $new_key) { + message::success(t("Your bit.ly API key has been saved.")); + } + if ($current_domain && $new_domain && $current_domain != $new_domain) { + message::success(t("Your preferrend bit.ly domain has been changed.")); + } else if (!$current_domain && $new_domain) { + message::success(t("Your preferred bit.ly domain has been set.")); + } + log::success("bitly", t("bit.ly login changed to %new_login", + array("new_login" => $new_login))); + log::success("bitly", t("bit.ly API key changed to %new_key", + array("new_key" => $new_key))); + + (!$new_login || !$new_key) ? $valid_config = false : $valid_config = true; + } + } + } + + $view = new Admin_View("admin.html"); + $view->page_title = t("bit.ly url shortner"); + $view->content = new View("admin_bitly.html"); + $view->content->login = $form->configure_bitly->login->value; + $view->content->api_key = $form->configure_bitly->api_key->value; + $view->content->domain = $form->configure_bitly->domain->value; + $view->content->valid_config = $valid_config; + $view->content->form = $form; + if ($valid_config) { + // @todo Store/get G3's root bit.ly url, only shorten if it hasn't been stored. + $view->content->g3_url = bitly::shorten_url(bitly::build_link()); + } + print $view; + } + +} \ No newline at end of file diff --git a/3.1/modules/bitly/helpers/bitly.php b/3.1/modules/bitly/helpers/bitly.php new file mode 100644 index 00000000..b69f7fe1 --- /dev/null +++ b/3.1/modules/bitly/helpers/bitly.php @@ -0,0 +1,257 @@ + 'expand', + 'shorten' => 'shorten', + 'validate' => 'validate', + 'clicks' => 'clicks', + 'referrers' => 'referrers', + 'countries' => 'countries', + 'clicks_by_minute' => 'clicks_by_minute', + 'clicks_by_day' => 'clicks_by_day', + 'lookup' => 'lookup', + 'info' => 'info', + ); + + static function get_configure_form() { + $form = new Forge("admin/bitly", "", "post", array("id" => "g-configure-bitly-form")); + $group = $form->group("configure_bitly")->label(t("Configure bit.ly")); + $group->input("login") + ->label(t("Login")) + ->value(module::get_var("bitly", "login")) + ->rules("required") + ->error_messages("required", t("You must enter a login")); + $group->input("api_key") + ->label(t("API Key")) + ->value(module::get_var("bitly", "api_key")) + ->rules("required") + ->error_messages("required", t("You must enter an API key")); + $group->dropdown("domain") + ->label(t("Preferred Domain")) + ->options(array("bit.ly" => "bit.ly", "j.mp" => "j.mp")) + ->selected(module::get_var("bitly", "domain")); + $group->submit("")->value(t("Save")); + return $form; + } + + /** + * Check a login and an API Key against bit.ly to make sure they're valid + * @param string $login the login + * @param string $api_key the API key + * @return boolean + */ + static function validate_config($login, $api_key) { + if (!empty($login) && !empty($api_key)) { + $parameters = array( + 'login' => $login, + 'apiKey' => $api_key, + 'x_login' => $login, + 'x_apiKey' => $api_key + ); + $request = self::_build_http_request('validate', $parameters); + $response = self::_http_post($request, "api.bit.ly"); + $json_decoded = json_decode($response->body[0]); + if (!$json_decoded->data->valid) { + if ("INVALID_LOGIN" == $json_decoded->status_txt) { + message::error(t("Your bit.ly login is incorrect")); + } else if ("INVALID_APIKEY" == $json_decoded->status_txt) { + message::error(t("Your bit.ly API Key is incorrect.")); + } + return false; + } else { + return true; + } + } + } + + /** + * Check whether the module's configured correctly + * @return boolean + */ + static function check_config() { + $login = module::get_var("bitly", "login"); + $api_key = module::get_var("bitly", "api_key"); + if (empty($login) || empty($api_key)) { + site_status::warning( + t("bit.ly is not quite ready! Please provide a login and API Key", + array("url" => html::mark_clean(url::site("admin/bitly")))), + "bitly_config"); + + } else if (!self::validate_config($login, $api_key)) { + site_status::warning( + t("bit.ly is not properly configured! URLs will not be shortened until its configuration is updated.", + array("url" => html::mark_clean(url::site("admin/bitly")))), + "bitly_config"); + } else { + site_status::clear("bitly_config"); + return true; + } + return false; + } + + /** + * + * @param $type + * @param $parameters + * @return string + */ + private static function _build_http_request($type, $parameters) { + $http_request = ''; + if (!empty($type) && count($parameters)) { + foreach($parameters as $k => $v) { + $query_string[] = "$k=" . urlencode($v); + } + $path = "/" . self::$api_version . "/$type?" . implode('&', $query_string); + $module_version = module::get_version("bitly"); + + $http_request = "GET $path HTTP/1.0\r\n"; + $http_request .= "Host: " . self::$api_host . "\r\n"; + $http_request .= "User-Agent: Gallery/3 | bitly/" . module::get_version("bitly") . "\r\n"; + $http_request .= "\r\n"; + $http_request .= $path; + } + return $http_request; + } + + /** + * Send an http POST request + * @param string $http_request + * @param string $host + * @return object + */ + private static function _http_post($http_request) { + $response = ''; + //Kohana_Log::add("debug", "Send request\n" . print_r($http_request, 1)); + if (false !== ($fs = @fsockopen(self::$api_host, 80, $errno, $errstr, 5))) { + fwrite($fs, $http_request); + while ( !feof($fs) ) { + $response .= fgets($fs, 1160); // One TCP-IP packet + } + fclose($fs); + list($headers, $body) = explode("\r\n\r\n", $response); + $headers = explode("\r\n", $headers); + $body = explode("\r\n", $body); + $response = new ArrayObject( + array("headers" => $headers, "body" => $body), ArrayObject::ARRAY_AS_PROPS); + } else { + throw new Exception("@todo CONNECTION TO URL SHORTENING SERVICE FAILED"); + } + Kohana_Log::add("debug", "Received response\n" . print_r($response, 1)); + + return $response; + } + + static function build_link($path='/') { + $protocol = strtolower(substr($_SERVER["SERVER_PROTOCOL"], 0, 5)) == 'https' ? 'https' : 'http'; + return url::site($path, $protocol); + } + + /** + * Shorten a Gallery URL + * @param string $long_url + * @param string $format + * @return string + */ + static function shorten_url($long_url, $format='json') { + $short_url = ''; + $parameters = array( + "login" => module::get_var("bitly", "login"), + 'apiKey' => module::get_var("bitly", "api_key"), + 'longUrl' => $long_url, + 'domain' => module::get_var("bitly", "domain"), + 'format' => $format, + ); + $request = self::_build_http_request('shorten', $parameters); + $response = self::_http_post($request, self::$api_host); + $json_decoded = json_decode($response->body[0]); + if ('OK' == $json_decoded->status_txt) { + // Save the original item id, the hash, and possibly the global hash, to the database + $short_url = $json_decoded->data->url; + $hash = $json_decoded->data->hash; + $global_hash = $json_decoded->data->global_hash; + $new_hash = $json_decoded->data->new_hash; + message::success("The $long_url has been shortened to $short_url"); + } else { + message::error("Unable to shorten the url"); + // @todo log the error + } + return $short_url; + } + + /** + * returns expanded url + * { + "status_code": 200, + "data": { + "expand": [ + { + "short_url": "http://tcrn.ch/a4MSUH", + "global_hash": "bWw49z", + "long_url": "http://www.techcrunch.com/2010/01/29/windows-mobile-foursquare/", + "user_hash": "a4MSUH" + }, + { + "short_url": "http://bit.ly/1YKMfY", + "global_hash": "1YKMfY", + "long_url": "http://betaworks.com/", + "user_hash": "1YKMfY" + }, + { + "long_url": "http://www.scotster.com/qf/?1152", + "global_hash": "lLWr", + "hash": "j3", + "user_hash": "j3" + }, + { + "hash": "a35.", + "error": "NOT_FOUND" + } + ] + }, + "status_txt": "OK" + } + */ + /** + * + * @param $short_url + * @param $hash + * @param $format + * @return + */ + static function expand_url($short_url, $hash=null, $format='json') { + $parameters = array( + "login" => module::get_var("bitly", "login"), + 'apiKey' => module::get_var("bitly", "api_key"), + 'shortUrl' => $short_url, + 'hash' => $hash, + ); + $request = self::_build_http_request('expand', $parameters); + $response = self::_http_post($http_request, self::$api_host); + return $response; + } + +} diff --git a/3.1/modules/bitly/helpers/bitly_event.php b/3.1/modules/bitly/helpers/bitly_event.php new file mode 100644 index 00000000..49ea72a6 --- /dev/null +++ b/3.1/modules/bitly/helpers/bitly_event.php @@ -0,0 +1,50 @@ +get("settings_menu") + ->append(Menu::factory("link") + ->id("bitly_menu") + ->label(t("Bit.ly")) + ->url(url::site("admin/bitly"))); + } + + static function site_menu($menu, $theme) { + $item = $theme->item(); + if ($item && $item->type == "photo") { + $menu->get("options_menu") + ->append(Menu::factory("link") + ->id("bitly") + ->label(t("Shorten Link with bit.ly")) + ->url(url::site("bitly/shorten_link/$item->id?csrf=$theme->csrf")) + ->css_id("g-bitly-link") + ->css_class("g-print-bitly-link ui-icon-print")); + } + } + + static function context_menu($menu, $theme, $item) { + $menu->get("options_menu") + ->append(Menu::factory("link") + ->id("bitly") + ->label(t("Shorten Link with bit.ly")) + ->url(url::site("bitly/shorten_link/$item->id?csrf=$theme->csrf")) + ->css_class("g-bitly-link ui-icon-link")); + } +} diff --git a/3.1/modules/bitly/helpers/bitly_installer.php b/3.1/modules/bitly/helpers/bitly_installer.php new file mode 100644 index 00000000..c847ec7c --- /dev/null +++ b/3.1/modules/bitly/helpers/bitly_installer.php @@ -0,0 +1,38 @@ +query("CREATE TABLE {bitly_urls} ( + `id` int(9) NOT NULL AUTO_INCREMENT, + `item_id` int(9) NOT NULL, + `hash` char(6) NOT NULL, + `user_id` int(9) NOT NULL, + PRIMARY KEY (`id`)) + DEFAULT CHARSET=utf8;"); + module::set_version("bitly", 1); + bitly::check_config(); + } + + static function deactivate() { + site_status::clear("bitly_config"); + } +} diff --git a/3.1/modules/bitly/helpers/bitly_theme.php b/3.1/modules/bitly/helpers/bitly_theme.php new file mode 100644 index 00000000..41aba38f --- /dev/null +++ b/3.1/modules/bitly/helpers/bitly_theme.php @@ -0,0 +1,24 @@ +script("bitly.js"); + } +} diff --git a/3.1/modules/bitly/js/bitly.js b/3.1/modules/bitly/js/bitly.js new file mode 100644 index 00000000..35bcd58b --- /dev/null +++ b/3.1/modules/bitly/js/bitly.js @@ -0,0 +1,8 @@ +$(document).ready(function() { + $(".g-bitly-link").click(function(e) { + e.preventDefault(); + return; + }); +}); + + diff --git a/3.1/modules/bitly/models/bitly.php b/3.1/modules/bitly/models/bitly.php new file mode 100644 index 00000000..a1b68600 --- /dev/null +++ b/3.1/modules/bitly/models/bitly.php @@ -0,0 +1,29 @@ + +
+

+

+ bit.ly account which will provide an API Key, which is also free.", + array("api_key_url" => "http://bit.ly/a/your_api_key", + "bitly_url" => "http://bit.ly")) ?> +

+
+ +
+ %g3_url", array('g3_url' => $g3_url)) ?> +
+ + + +
+