├── CDN.alfredworkflow ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── current-version.json ├── screenshots ├── alfred.png ├── all.png └── cloudflare.png └── src ├── cdn.php ├── cdns.json ├── icon-cache ├── cloudflare.png ├── google.png ├── jsdelivr.png └── msn.png ├── icon-src ├── cloudflare.png ├── google.png ├── jsdelivr.png └── msn.png ├── icon.png ├── update.json └── workflows.php /CDN.alfredworkflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/CDN.alfredworkflow -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | First off, thanks for you interest in contributing. Everyone who uses this repos really appreciates it. 3 | 4 | ![alt text][alfred] 5 | 6 | ## Issues 7 | All are welcome. 8 | 9 | ## Pull Requests 10 | Good pull requests - patches, improvements, new features - are a fantastic help. 11 | They should remain focused in scope and avoid containing unrelated commits. If 12 | your contribution involves a significant amount of work or substantial changes 13 | to any part of the project, please open an issue to discuss it first. 14 | 15 | Make sure to adhere to the coding conventions used throughout a project 16 | (indentation, accurate comments, etc.). Please update any documentation that is 17 | relevant to the change you're making. 18 | 19 | ## Pull Request Checklist 20 | Before you submit your PR please make sure everything is in order. 21 | 22 | - [ ] Installed `.alfredworkflow` file from repo before making changes. 23 | - [ ] Update the version in the workflow title. Double-click the workflow to edit. 24 | - [ ] Increase the version number in `update.json`. Right-click the workflow in Alfred, click `Show in Finder`. The `update.json` file will be in that folder. 25 | 26 | - [ ] Increase the version number in `current-version.json`. 27 | - [ ] If needed include a large icon in the `src/icon-src/` folder that has square dimensions. 28 | - [ ] If needed include a cached icon in the `sec/icon-cache/` folder that 256x256 pixels. Alfred creates these when you insert an image into a workflow. You can get this from inside the `.alfredworkflow`. Right-click the workflow in Alfred, click `Show in Finder`. The `--hash-value--.png` file will be in that folder. Copy to `/src/icon-cache` and rename. 29 | - [ ] If needed add a screenshot. Use ⌘ (command) + ⇧ (shift) + 4, press ␣ (space), then click on the Alfred window to create a clean screen shot. Place in the `screenshots` folder. 30 | - [ ] Update README.md with new version and any additional screenshots. 31 | - [ ] Export workflow to repo folder. Right-click the workflow in Alfred, click `Export...`. Don't include the `(v1.0)` in the name. 32 | 33 | ## Pull Request Process 34 | Please follow this process; it's the best way to get your work included in the 35 | project: 36 | 37 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, 38 | and configure the remotes: 39 | 40 | ```bash 41 | # Clones your fork of the repo into the current directory in terminal 42 | git clone https://github.com//.git 43 | # Navigate to the newly cloned directory 44 | cd 45 | # Assigns the original repo to a remote called "upstream" 46 | git remote add upstream https://github.com//.git 47 | ``` 48 | 49 | 2. If you cloned a while ago, get the latest changes from upstream: 50 | 51 | ```bash 52 | git checkout master 53 | git pull upstream master 54 | ``` 55 | 56 | 3. Create a new topic branch to contain your feature, change, or fix: 57 | 58 | ```bash 59 | git checkout -b 60 | ``` 61 | 62 | 4. Commit your changes in logical chunks. Please adhere to these [git commit 63 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 64 | or your pull request is unlikely be merged into the main project. Use git's 65 | [interactive rebase](https://help.github.com/articles/interactive-rebase) 66 | feature to tidy up your commits before making them public. 67 | 68 | 5. Locally merge (or rebase) the upstream development branch into your topic 69 | branch: 70 | 71 | ```bash 72 | git pull [--rebase] upstream master 73 | ``` 74 | 75 | 6. Push your topic branch up to your fork: 76 | 77 | ```bash 78 | git push origin 79 | ``` 80 | 81 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests) 82 | with a clear title and description. 83 | 84 | [alfred]: ./screenshots/alfred.png "Alfred Workflow" 85 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 will Farrell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CDN ([Download v1.5](https://raw.github.com/willfarrell/alfred-cdn-workflow/master/CDN.alfredworkflow)) 2 | 3 | Check which CDNs a package is hosted on. 4 | 5 | ## Requirements 6 | 1. [Alfred App v2](http://www.alfredapp.com/#download) 7 | 1. [Alfred Powerpack](https://buy.alfredapp.com/) 8 | 9 | ## Installing 10 | 1. Click the download buttons below 11 | 2. Double-click to import into Alfred 2 12 | 3. Review the workflow to add custom Hotkeys 13 | 14 | ## Updating 15 | Run the [Alleyoop Workflow](http://www.alfredforum.com/topic/1582-alleyoop-update-alfred-workflows/) using the keyword `oop`. If you're not comfortable with Alleyoop, **star & watch this repo** to keep up to date on new versions and additional workflows. 16 | 17 | ## About 18 | 19 | ![alt text][all] 20 | ![alt text][cloudflare] 21 | 22 | ## Commands 23 | - `cdn all {query}` - Search all CDNs 24 | - `cdn js {query}` - Search JsDelivr CDN ([www.jsdelivr.com/](http://www.jsdelivr.com/)) 25 | - `cdn cf {query}` - Search Cloud Flare CDN ([cdnjs.com](http://cdnjs.com)) 26 | - `cdn g {query}` - Search Google CDN 27 | - `cdn msn {query}` - Search MSN CDN 28 | 29 | ## Contributors 30 | - [@willfarrell](https://github.com/willfarrell) 31 | 32 | [all]: ./screenshots/all.png "Sample Options" 33 | [cloudflare]: ./screenshots/cloudflare.png "Sample CloudFlare Search" -------------------------------------------------------------------------------- /current-version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.5, 3 | "download_url": "https://raw.github.com/willfarrell/alfred-cdn-workflow/master/CDN.alfredworkflow", 4 | "description": "Check which CDNs a package is hosted on." 5 | } 6 | -------------------------------------------------------------------------------- /screenshots/alfred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/screenshots/alfred.png -------------------------------------------------------------------------------- /screenshots/all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/screenshots/all.png -------------------------------------------------------------------------------- /screenshots/cloudflare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/screenshots/cloudflare.png -------------------------------------------------------------------------------- /src/cdn.php: -------------------------------------------------------------------------------- 1 | $params) { 37 | $count = count( $w->results() ); 38 | 39 | $pos = strpos($cdn, $cdn_q); 40 | if ($pos !== false && $pos == 0) { 41 | run($params, $string); 42 | if ($count == count($w->results())) { 43 | $w->result( "cdn-$cdn", $query, 'No libraries found.', $query, "icon-cache/$cdn.png", 'no' ); 44 | } 45 | } 46 | 47 | } 48 | 49 | } 50 | 51 | // 52 | if ( count( $w->results() ) == 0 ) { 53 | foreach($cdns as $cdn => $params) { 54 | $count = count( $w->results() ); 55 | run($params, $query); 56 | if ($count == count($w->results())) { 57 | $w->result( "cdn-$cdn", $query, "{$params->name}", 'No libraries found.', "icon-cache/$cdn.png", 'no' ); 58 | } 59 | } 60 | } 61 | 62 | function load($params) { 63 | global $w; 64 | // get db 65 | //console("READ {$params->id}CDN.json"); 66 | $pkgs = $w->read("{$params->id}CDN.json"); 67 | $timestamp = $w->filetime("{$params->id}CDN.json"); 68 | if ( debug || !$pkgs || $timestamp < (time() - 7 * 86400) ) { 69 | //console("SEARCH {$params->id}CDN.json"); 70 | $id = $params->id; 71 | $data = $id( ($params->db_url) ? $params->db_url : $params->site); 72 | $w->write($data, "{$params->id}CDN.json"); 73 | //console($data); 74 | $pkgs = json_decode( $data ); 75 | //console("WRITE {$params->id}CDN.json"); 76 | }/* else if (!$pkgs) { 77 | // add in db gen scripts 78 | 79 | $data = $id($params->site); 80 | 81 | 82 | $data = '{"packages":[]}'; 83 | $pkgs = json_decode( $data ); 84 | }*/ 85 | //console($pkgs); 86 | $pkgs = $pkgs->packages; 87 | return $pkgs; 88 | } 89 | 90 | function search($plugin, $query) { 91 | //console("SEARCH"); 92 | //console($plugin); 93 | if (isset($plugin->name)) { 94 | $name = strtolower(trim($plugin->name)); 95 | if (strpos($name, $query) === 0) { 96 | return 1; 97 | } else if (strpos($name, $query) > 0) { 98 | return 2; 99 | } else if(strpos($name, $query) !== false) { 100 | return 3; 101 | } else if (isset($plugin->description) && strpos(strtolower(trim($plugin->description)), $query) !== false) { 102 | return 4; 103 | } else if (isset($plugin->keywords)) { 104 | foreach($plugin->keywords as $keyword) { 105 | if (strpos(strtolower(trim($keyword)), $query) !== false) { 106 | return 5; 107 | } 108 | } 109 | } 110 | } 111 | return 0; 112 | } 113 | 114 | function run($params, $query) { 115 | global $w; 116 | 117 | $pkgs = load($params); 118 | $output = array(); 119 | for($i = 0, $l = sizeof($pkgs); $i < $l; $i++) { 120 | $pkg = $pkgs[$i]; 121 | $priority = search($pkg, $query); 122 | if ($priority) { 123 | //console("FOUND {$priority}"); 124 | $title = $pkg->name." (".$pkg->version.")"; // remove grunt- from title 125 | 126 | $url = $params->url; 127 | $url = str_replace("{name}", $pkg->name, $url); 128 | $url = str_replace("{filename}", $pkg->filename, $url); 129 | $url = str_replace("{version}", $pkg->version, $url); 130 | 131 | $output[$priority][] = array( 132 | "id" => "cdn-{$params->id}-{$pkg->name}", 133 | "value" => $url, 134 | "title" => $title, 135 | "details" => $pkg->description, 136 | "icon" => "icon-cache/{$params->id}.png" 137 | ); 138 | 139 | } 140 | } 141 | 142 | // print out order 143 | $count = 15; // 15 144 | foreach($output as $list) { 145 | foreach($list as $item) { 146 | $w->result( $item["id"], $item["value"], $item["title"], $item["details"], $item["icon"], "yes" ); 147 | if (!--$count) { break; } 148 | } 149 | } 150 | } 151 | 152 | /*if ( count( $w->results() ) == 0 ) { 153 | $w->result( 'cdn', $query, 'No libraries found.', $query, 'icon.png', 'no' ); 154 | }*/ 155 | 156 | // build cloudflare DB 157 | function cloudflare($url) { 158 | global $w; 159 | return $w->request($url); 160 | } 161 | 162 | // build google DB 163 | function google($url) { 164 | global $w; 165 | $data = $w->request($url); 166 | 167 | if ($debug && $data == '') { 168 | console('URL has likely changed.'); 169 | console($data); 170 | } 171 | preg_match_all('/

(.*?)<\/h3>\s*
[\s\S]*?src="(.*?)"[\s\S]*?>(.*?)<\/a>/i', $data, $matches); 172 | //console($data); 173 | //console($matches); 174 | 175 | $json = array( 176 | "packages" => array() 177 | ); 178 | for($i = 0, $l = sizeof($matches[0]); $i < $l; $i++) { 179 | // https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js 180 | //console($matches[2][$i]); 181 | preg_match('/ajax\.googleapis\.com\/ajax\/libs\/([\w]*)\/([\d\.]*)\/([\s\S]*)/i', $matches[2][$i], $url_matches); 182 | //console($url_matches); 183 | 184 | //preg_match_all('/([\d\.]{3,9})/i', $matches[3][$i], $versions); 185 | //for($j = 0, $k = sizeof($versions[0]); $j < $k; $j++) { 186 | $json["packages"][] = array( 187 | "name" => $url_matches[1], // angularjs 188 | "description" => $matches[2][$i], // angularjs.org 189 | //"version" => $versions[1][$j], 190 | "version" => $url_matches[2], // 1.4.9 191 | "filename" => $url_matches[3], // 192 | "keywords" => array() 193 | ); 194 | //} 195 | } 196 | return json_encode($json); 197 | } 198 | 199 | // build msn DB 200 | function msn($url) { 201 | global $w; 202 | $data = $w->request($url); 203 | 204 | $json = array( 205 | "packages" => array() 206 | ); 207 | 208 | preg_match_all('/

([\w\s]*?) version ([\d\.]*)<\/h4>[\s\S]*?
  • http:\/\/ajax.aspnetcdn.com\/ajax\/([\s\S]*?)\/([\w\.]*)<\/li>/i', $data, $matches); 209 | for($i = 0, $l = sizeof($matches[0]); $i < $l; $i++) { 210 | $json["packages"][] = array( 211 | "name" => trim($matches[1][$i]), 212 | "description" => "", 213 | "version" => $matches[2][$i], 214 | "filename" => $matches[4][$i], 215 | "keywords" => array() 216 | ); 217 | } 218 | return json_encode($json); 219 | } 220 | 221 | // build jsdelivr DB 222 | function jsdelivr($url) { 223 | global $w; 224 | $data = $w->request($url); 225 | $data = json_decode($data, true); 226 | $json = array( 227 | "packages" => array() 228 | ); 229 | for($i = 0, $l = sizeof($data); $i < $l; $i++) { 230 | $json["packages"][] = array( 231 | "name" => $data[$i]['name'], 232 | "description" => $data[$i]['description'], 233 | "version" => $data[$i]['lastversion'], 234 | "filename" => $data[$i]['mainfile'], 235 | "keywords" => array() 236 | ); 237 | } 238 | return json_encode($json); 239 | } 240 | 241 | echo $w->toxml(); 242 | // **************** 243 | ?> -------------------------------------------------------------------------------- /src/cdns.json: -------------------------------------------------------------------------------- 1 | { 2 | "google": { 3 | "id":"google", 4 | "name":"Google - googleapis.com", 5 | "site":"https://developers.google.com/speed/libraries/#Libraries", 6 | "url":"//ajax.googleapis.com/ajax/libs/{name}/{version}/{filename}", 7 | "db_url":false 8 | }, 9 | "msn": { 10 | "id":"msn", 11 | "name":"Microsoft - aspnetcdn.com", 12 | "site":"http://www.asp.net/ajax/cdn", 13 | "url":"//ajax.aspnetcdn.com/ajax/{name}/{filename}", 14 | "db_url":false 15 | }, 16 | "cloudflare": { 17 | "id":"cloudflare", 18 | "name":"CloudFlare - cdnjs.com", 19 | "site":"http://cdnjs.com", 20 | "url":"//cdnjs.cloudflare.com/ajax/libs/{name}/{version}/{filename}", 21 | "db_url":"http://cdnjs.com/packages.json" 22 | }, 23 | "jsdelivr": { 24 | "id":"jsdelivr", 25 | "name":"JsDelivr - jsdelivr.com", 26 | "site":"http://www.jsdelivr.com", 27 | "url":"//cdn.jsdelivr.net/{name}/{version}/{filename}", 28 | "db_url":"http://api.jsdelivr.com/v1/jsdelivr/libraries?fields=name,lastversion,versions,description,mainfile" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/icon-cache/cloudflare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-cache/cloudflare.png -------------------------------------------------------------------------------- /src/icon-cache/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-cache/google.png -------------------------------------------------------------------------------- /src/icon-cache/jsdelivr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-cache/jsdelivr.png -------------------------------------------------------------------------------- /src/icon-cache/msn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-cache/msn.png -------------------------------------------------------------------------------- /src/icon-src/cloudflare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-src/cloudflare.png -------------------------------------------------------------------------------- /src/icon-src/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-src/google.png -------------------------------------------------------------------------------- /src/icon-src/jsdelivr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-src/jsdelivr.png -------------------------------------------------------------------------------- /src/icon-src/msn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon-src/msn.png -------------------------------------------------------------------------------- /src/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willfarrell/alfred-cdn-workflow/bfe7cfe7e120e51f5ad8e7d8004b777f207ebc87/src/icon.png -------------------------------------------------------------------------------- /src/update.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1.2, 3 | "remote_json": "https://raw.github.com/willfarrell/alfred-cdn-workflow/master/current-version.json" 4 | } -------------------------------------------------------------------------------- /src/workflows.php: -------------------------------------------------------------------------------- 1 | path = exec('pwd'); 31 | $this->home = exec('printf $HOME'); 32 | 33 | if ( file_exists( 'info.plist' ) ): 34 | $this->bundle = $this->get( 'bundleid', 'info.plist' ); 35 | endif; 36 | 37 | if ( !is_null( $bundleid ) ): 38 | $this->bundle = $bundleid; 39 | endif; 40 | 41 | $this->cache = $this->home. "/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/".$this->bundle; 42 | $this->data = $this->home. "/Library/Application Support/Alfred 2/Workflow Data/".$this->bundle; 43 | 44 | if ( !file_exists( $this->cache ) ): 45 | exec("mkdir '".$this->cache."'"); 46 | endif; 47 | 48 | if ( !file_exists( $this->data ) ): 49 | exec("mkdir '".$this->data."'"); 50 | endif; 51 | 52 | $this->results = array(); 53 | } 54 | 55 | /** 56 | * Description: 57 | * Accepts no parameter and returns the value of the bundle id for the current workflow. 58 | * If no value is available, then false is returned. 59 | * 60 | * @param none 61 | * @return false if not available, bundle id value if available. 62 | */ 63 | public function bundle() 64 | { 65 | if ( is_null( $this->bundle ) ): 66 | return false; 67 | else: 68 | return $this->bundle; 69 | endif; 70 | } 71 | 72 | /** 73 | * Description: 74 | * Accepts no parameter and returns the value of the path to the cache directory for your 75 | * workflow if it is available. Returns false if the value isn't available. 76 | * 77 | * @param none 78 | * @return false if not available, path to the cache directory for your workflow if available. 79 | */ 80 | public function cache() 81 | { 82 | if ( is_null( $this->bundle ) ): 83 | return false; 84 | else: 85 | if ( is_null( $this->cache ) ): 86 | return false; 87 | else: 88 | return $this->cache; 89 | endif; 90 | endif; 91 | } 92 | 93 | /** 94 | * Description: 95 | * Accepts no parameter and returns the value of the path to the storage directory for your 96 | * workflow if it is available. Returns false if the value isn't available. 97 | * 98 | * @param none 99 | * @return false if not available, path to the storage directory for your workflow if available. 100 | */ 101 | public function data() 102 | { 103 | if ( is_null( $this->bundle ) ): 104 | return false; 105 | else: 106 | if ( is_null( $this->data ) ): 107 | return false; 108 | else: 109 | return $this->data; 110 | endif; 111 | endif; 112 | } 113 | 114 | /** 115 | * Description: 116 | * Accepts no parameter and returns the value of the path to the current directory for your 117 | * workflow if it is available. Returns false if the value isn't available. 118 | * 119 | * @param none 120 | * @return false if not available, path to the current directory for your workflow if available. 121 | */ 122 | public function path() 123 | { 124 | if ( is_null( $this->path ) ): 125 | return false; 126 | else: 127 | return $this->path; 128 | endif; 129 | } 130 | 131 | /** 132 | * Description: 133 | * Accepts no parameter and returns the value of the home path for the current user 134 | * Returns false if the value isn't available. 135 | * 136 | * @param none 137 | * @return false if not available, home path for the current user if available. 138 | */ 139 | public function home() 140 | { 141 | if ( is_null( $this->home ) ): 142 | return false; 143 | else: 144 | return $this->home; 145 | endif; 146 | } 147 | 148 | /** 149 | * Description: 150 | * Returns an array of available result items 151 | * 152 | * @param none 153 | * @return array - list of result items 154 | */ 155 | public function results() 156 | { 157 | return $this->results; 158 | } 159 | 160 | /** 161 | * Description: 162 | * Convert an associative array into XML format 163 | * 164 | * @param $a - An associative array to convert 165 | * @param $format - format of data being passed (json or array), defaults to array 166 | * @return - XML string representation of the array 167 | */ 168 | public function toxml( $a=null, $format='array' ) { 169 | 170 | if ( $format == 'json' ): 171 | $a = json_decode( $a, TRUE ); 172 | endif; 173 | 174 | if ( is_null( $a ) && !empty( $this->results ) ): 175 | $a = $this->results; 176 | elseif ( is_null( $a ) && empty( $this->results ) ): 177 | return false; 178 | endif; 179 | 180 | $items = new SimpleXMLElement(""); // Create new XML element 181 | 182 | foreach( $a as $b ): // Lop through each object in the array 183 | $c = $items->addChild( 'item' ); // Add a new 'item' element for each object 184 | $c_keys = array_keys( $b ); // Grab all the keys for that item 185 | foreach( $c_keys as $key ): // For each of those keys 186 | if ( $key == 'uid' ): 187 | $c->addAttribute( 'uid', $b[$key] ); 188 | elseif ( $key == 'arg' ): 189 | $c->addAttribute( 'arg', $b[$key] ); 190 | elseif ( $key == 'type' ): 191 | $c->addAttribute( 'type', $b[$key] ); 192 | elseif ( $key == 'valid' ): 193 | if ( $b[$key] == 'yes' || $b[$key] == 'no' ): 194 | $c->addAttribute( 'valid', $b[$key] ); 195 | endif; 196 | elseif ( $key == 'autocomplete' ): 197 | $c->addAttribute( 'autocomplete', $b[$key] ); 198 | elseif ( $key == 'icon' ): 199 | if ( substr( $b[$key], 0, 9 ) == 'fileicon:' ): 200 | $val = substr( $b[$key], 9 ); 201 | $c->$key = $val; 202 | $c->$key->addAttribute( 'type', 'fileicon' ); 203 | elseif ( substr( $b[$key], 0, 9 ) == 'filetype:' ): 204 | $val = substr( $b[$key], 9 ); 205 | $c->$key = $val; 206 | $c->$key->addAttribute( 'type', 'filetype' ); 207 | else: 208 | $c->$key = $b[$key]; 209 | endif; 210 | else: 211 | $c->$key = $b[$key]; 212 | endif; 213 | endforeach; 214 | endforeach; 215 | 216 | return $items->asXML(); // Return XML string representation of the array 217 | 218 | } 219 | 220 | /** 221 | * Description: 222 | * Remove all items from an associative array that do not have a value 223 | * 224 | * @param $a - Associative array 225 | * @return bool 226 | */ 227 | private function empty_filter( $a ) { 228 | if ( $a == '' || $a == null ): // if $a is empty or null 229 | return false; // return false, else, return true 230 | else: 231 | return true; 232 | endif; 233 | } 234 | 235 | /** 236 | * Description: 237 | * Save values to a specified plist. If the first parameter is an associative 238 | * array, then the second parameter becomes the plist file to save to. If the 239 | * first parameter is string, then it is assumed that the first parameter is 240 | * the label, the second parameter is the value, and the third parameter is 241 | * the plist file to save the data to. 242 | * 243 | * @param $a - associative array of values to save 244 | * @param $b - the value of the setting 245 | * @param $c - the plist to save the values into 246 | * @return string - execution output 247 | */ 248 | public function set( $a=null, $b=null, $c=null ) 249 | { 250 | if ( is_array( $a ) ): 251 | if ( file_exists( $b ) ): 252 | if ( file_exists( $this->path.'/'.$b ) ): 253 | $b = $this->path.'/'.$b; 254 | endif; 255 | elseif ( file_exists( $this->data."/".$b ) ): 256 | $b = $this->data."/".$b; 257 | elseif ( file_exists( $this->cache."/".$b ) ): 258 | $b = $this->cache."/".$b; 259 | else: 260 | $b = $this->data."/".$b; 261 | endif; 262 | else: 263 | if ( file_exists( $c ) ): 264 | if ( file_exists( $this->path.'/'.$c ) ): 265 | $c = $this->path.'/'.$c; 266 | endif; 267 | elseif ( file_exists( $this->data."/".$c ) ): 268 | $c = $this->data."/".$c; 269 | elseif ( file_exists( $this->cache."/".$c ) ): 270 | $c = $this->cache."/".$c; 271 | else: 272 | $c = $this->data."/".$c; 273 | endif; 274 | endif; 275 | 276 | if ( is_array( $a ) ): 277 | foreach( $a as $k => $v ): 278 | exec( 'defaults write "'. $b .'" '. $k .' "'. $v .'"'); 279 | endforeach; 280 | else: 281 | exec( 'defaults write "'. $c .'" '. $a .' "'. $b .'"'); 282 | endif; 283 | } 284 | 285 | /** 286 | * Description: 287 | * Read a value from the specified plist 288 | * 289 | * @param $a - the value to read 290 | * @param $b - plist to read the values from 291 | * @return bool false if not found, string if found 292 | */ 293 | public function get( $a, $b ) { 294 | 295 | if ( file_exists( $b ) ): 296 | if ( file_exists( $this->path.'/'.$b ) ): 297 | $b = $this->path.'/'.$b; 298 | endif; 299 | elseif ( file_exists( $this->data."/".$b ) ): 300 | $b = $this->data."/".$b; 301 | elseif ( file_exists( $this->cache."/".$b ) ): 302 | $b = $this->cache."/".$b; 303 | else: 304 | return false; 305 | endif; 306 | 307 | exec( 'defaults read "'. $b .'" '.$a, $out ); // Execute system call to read plist value 308 | 309 | if ( $out == "" ): 310 | return false; 311 | endif; 312 | 313 | $out = $out[0]; 314 | return $out; // Return item value 315 | } 316 | 317 | /** 318 | * Description: 319 | * Read data from a remote file/url, essentially a shortcut for curl 320 | * 321 | * @param $url - URL to request 322 | * @param $options - Array of curl options 323 | * @return result from curl_exec 324 | */ 325 | public function request( $url=null, $options=null ) 326 | { 327 | if ( is_null( $url ) ): 328 | return false; 329 | endif; 330 | 331 | $defaults = array( // Create a list of default curl options 332 | //CURLOPT_VERBOSE => true, 333 | CURLOPT_RETURNTRANSFER => true, // Returns the result as a string 334 | CURLOPT_URL => $url, // Sets the url to request 335 | CURLOPT_FRESH_CONNECT => true, 336 | CURLOPT_AUTOREFERER => true, 337 | CURLOPT_RETURNTRANSFER => true, 338 | CURLOPT_FOLLOWLOCATION => true 339 | CURLOPT_USERAGENT => 'alfred-workflow' 340 | ); 341 | 342 | if ( $options ): 343 | foreach( $options as $k => $v ): 344 | $defaults[$k] = $v; 345 | endforeach; 346 | endif; 347 | 348 | array_filter( $defaults, // Filter out empty options from the array 349 | array( $this, 'empty_filter' ) ); 350 | 351 | $ch = curl_init(); // Init new curl object 352 | curl_setopt_array( $ch, $defaults ); // Set curl options 353 | $out = curl_exec( $ch ); // Request remote data 354 | $err = curl_error( $ch ); 355 | curl_close( $ch ); // End curl request 356 | 357 | if ( $err ): 358 | return $err; 359 | else: 360 | return $out; 361 | endif; 362 | } 363 | 364 | /** 365 | * Description: 366 | * Allows searching the local hard drive using mdfind 367 | * 368 | * @param $query - search string 369 | * @return array - array of search results 370 | */ 371 | public function mdfind( $query ) 372 | { 373 | exec('mdfind "'.$query.'"', $results); 374 | return $results; 375 | } 376 | 377 | public function delete( $a ) 378 | { 379 | if ( file_exists( $a ) ): 380 | if ( file_exists( $this->path.'/'.$a ) ): 381 | unlink($this->path.'/'.$a); 382 | endif; 383 | elseif ( file_exists( $this->data."/".$a ) ): 384 | unlink($this->data."/".$a); 385 | elseif ( file_exists( $this->cache."/".$a ) ): 386 | unlink($this->cache."/".$a); 387 | endif; 388 | } 389 | 390 | /** 391 | * Description: 392 | * Accepts data and a string file name to store data to local file as cache 393 | * 394 | * @param array - data to save to file 395 | * @param file - filename to write the cache data to 396 | * @return none 397 | */ 398 | public function write( $a, $b ) 399 | { 400 | if ( file_exists( $b ) ): 401 | if ( file_exists( $this->path.'/'.$b ) ): 402 | $b = $this->path.'/'.$b; 403 | endif; 404 | elseif ( file_exists( $this->data."/".$b ) ): 405 | $b = $this->data."/".$b; 406 | elseif ( file_exists( $this->cache."/".$b ) ): 407 | $b = $this->cache."/".$b; 408 | else: 409 | $b = $this->data."/".$b; 410 | endif; 411 | 412 | if ( is_array( $a ) ): 413 | $a = json_encode( $a ); 414 | file_put_contents( $b, $a ); 415 | return true; 416 | elseif ( is_string( $a ) ): 417 | file_put_contents( $b, $a ); 418 | return true; 419 | else: 420 | return false; 421 | endif; 422 | } 423 | 424 | /** 425 | * Description: 426 | * Returns data from a local cache file 427 | * 428 | * @param file - filename to read the cache data from 429 | * @return false if the file cannot be found, the file data if found. If the file 430 | * format is json encoded, then a json object is returned. 431 | */ 432 | public function read( $a ) 433 | { 434 | if ( file_exists( $a ) ): 435 | if ( file_exists( $this->path.'/'.$a ) ): 436 | $a = $this->path.'/'.$a; 437 | endif; 438 | elseif ( file_exists( $this->data."/".$a ) ): 439 | $a = $this->data."/".$a; 440 | elseif ( file_exists( $this->cache."/".$a ) ): 441 | $a = $this->cache."/".$a; 442 | else: 443 | return false; 444 | endif; 445 | 446 | $out = file_get_contents( $a ); 447 | if ( !is_null( json_decode( $out ) ) ): 448 | $out = json_decode( $out ); 449 | endif; 450 | 451 | return $out; 452 | } 453 | 454 | public function filetime( $a ) 455 | { 456 | if ( file_exists( $a ) ): 457 | if ( file_exists( $this->path.'/'.$a ) ): 458 | return filemtime($this->path.'/'.$a); 459 | endif; 460 | elseif ( file_exists( $this->data."/".$a ) ): 461 | return filemtime($this->data.'/'.$a); 462 | elseif ( file_exists( $this->cache."/".$a ) ): 463 | return filemtime($this->cache.'/'.$a); 464 | endif; 465 | 466 | return false; 467 | } 468 | 469 | /** 470 | * Description: 471 | * Helper function that just makes it easier to pass values into a function 472 | * and create an array result to be passed back to Alfred 473 | * 474 | * @param $uid - the uid of the result, should be unique 475 | * @param $arg - the argument that will be passed on 476 | * @param $title - The title of the result item 477 | * @param $sub - The subtitle text for the result item 478 | * @param $icon - the icon to use for the result item 479 | * @param $valid - sets whether the result item can be actioned 480 | * @param $auto - the autocomplete value for the result item 481 | * @return array - array item to be passed back to Alfred 482 | */ 483 | public function result( $uid, $arg, $title, $sub, $icon, $valid='yes', $auto=null, $type=null ) 484 | { 485 | $temp = array( 486 | 'uid' => $uid, 487 | 'arg' => $arg, 488 | 'title' => $title, 489 | 'subtitle' => $sub, 490 | 'icon' => $icon, 491 | 'valid' => $valid, 492 | 'autocomplete' => $auto, 493 | 'type' => $type 494 | ); 495 | 496 | if ( is_null( $type ) ): 497 | unset( $temp['type'] ); 498 | endif; 499 | 500 | array_push( $this->results, $temp ); 501 | 502 | return $temp; 503 | } 504 | 505 | } --------------------------------------------------------------------------------