PluginProbe
WPIDE – File Manager & Code Editor / 2.3.2
WPIDE – File Manager & Code Editor v2.3.2
3.5.8 3.5.7 2.0.14 2.0.15 2.0.16 2.0.2 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1 2.2 2.3 2.3.1 2.3.2 2.4.0 2.5 2.6 3.0 3.1 3.2 3.3 3.4 All 54 releases
wpide / WPide.php

WPide.php in WPIDE – File Manager & Code Editor 2.3.2, at WPide.php

1,463 lines 62.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 Plugin Name: WPide
4 Plugin URI: https://github.com/WPsites/WPide
5 Description: WordPress code editor with auto completion of both WordPress and PHP functions with reference, syntax highlighting, line numbers, tabbed editing, automatic backup.
6 Version: 2.3.2
7 Author: Simon @ WPsites
8 Author URI: http://www.wpsites.co.uk
9 */
10
11 // Exit if accessed directly
12 if ( !defined( 'ABSPATH' ) ) exit;
13
14
15 if ( !class_exists( 'wpide' ) ) :
16 class wpide
17
18 {
19
20 public $site_url, $plugin_url, $git, $git_repo_path;
21
22 /**
23 * The main WPide loader (PHP4 compatable)
24 *
25 * @uses wpide::__construct() Setup the globals needed
26 */
27 public function wpide() {
28 $this->__construct();
29 }
30
31 function __construct() {
32
33 //add WPide to the menu
34 add_action( 'admin_menu', array( $this, 'add_my_menu_page' ) );
35
36 //hook for processing incoming image saves
37 if ( isset($_GET['wpide_save_image']) ){
38
39 //force local file method for testing - you could force other methods 'direct', 'ssh', 'ftpext' or 'ftpsockets'
40 $this->override_fs_method('direct');
41
42 add_action('admin_init', array( $this, 'wpide_save_image') );
43
44 }
45
46
47 //only include this plugin if on theme editor, plugin editor or an ajax call
48 if ( (isset($_GET['page']) && $_GET['page'] === 'wpide') ||
49 preg_match('#admin-ajax\.php$#', $_SERVER['PHP_SELF']) ){
50
51
52 // force local file method until I've worked out how to implement the other methods
53 // main problem being password wouldn't/isn't saved between requests
54 // you could force other methods 'direct', 'ssh', 'ftpext' or 'ftpsockets'
55 $this->override_fs_method('direct');
56
57 // Uncomment any of these calls to add the functionality that you need.
58 add_action('admin_init', array( $this, 'add_admin_js' ) );
59 add_action('admin_init', array( $this, 'add_admin_styles' ) );
60
61 //setup jqueryFiletree list callback
62 add_action('wp_ajax_jqueryFileTree', array( $this, 'jqueryFileTree_get_list' ) );
63 //setup ajax function to get file contents for editing
64 add_action('wp_ajax_wpide_get_file', array( $this, 'wpide_get_file' ) );
65 //setup ajax function to save file contents and do automatic backup if needed
66 add_action('wp_ajax_wpide_save_file', array( $this, 'wpide_save_file' ) );
67 //setup ajax function to create new item (folder, file etc)
68 add_action('wp_ajax_wpide_create_new', array( $this, 'wpide_create_new' ) );
69 //setup ajax function to show local git repo changes
70 add_action('wp_ajax_wpide_git_status', array( $this, 'git_status' ) );
71 //setup ajax function to show diff
72 add_action('wp_ajax_wpide_git_diff', array( $this, 'git_diff' ) );
73 //setup ajax function to commit changes
74 add_action('wp_ajax_wpide_git_commit', array( $this, 'git_commit' ) );
75 //setup ajax function to view the git log
76 add_action('wp_ajax_wpide_git_log', array( $this, 'git_log' ) );
77 //setup ajax function to initiate a git repo
78 add_action('wp_ajax_wpide_git_init', array( $this, 'git_init' ) );
79 //setup ajax function to clone a remote
80 add_action('wp_ajax_wpide_git_clone', array( $this, 'git_clone' ) );
81 //setup ajax function to push to remote
82 add_action('wp_ajax_wpide_git_push', array( $this, 'git_push' ) );
83 //setup ajax function to view/generate ssh key and known host file
84 add_action('wp_ajax_wpide_git_ssh_gen', array( $this, 'git_ssh_gen' ) );
85
86
87
88 //setup ajax function to create new item (folder, file etc)
89 add_action('wp_ajax_wpide_image_edit_key', array( $this, 'wpide_image_edit_key' ) );
90
91 //setup ajax function for startup to get some debug info, checking permissions etc
92 add_action('wp_ajax_wpide_startup_check', array( $this, 'wpide_startup_check' ) );
93
94 //add a warning when navigating away from WPide
95 //it has to go after WordPress scripts otherwise WP clears the binding
96 add_action('admin_print_footer_scripts', array( $this, 'add_admin_nav_warning' ), 99 );
97
98 // Add body class to collapse the wp sidebar nav
99 add_filter('admin_body_class', array( $this, 'hide_wp_sidebar_nav' ), 11);
100
101 //hide the update nag
102 add_action('admin_menu', array( $this, 'hide_wp_update_nag' ));
103
104 }
105
106
107
108
109
110 $this->site_url = get_bloginfo('url');
111
112
113 }
114
115
116 public function override_fs_method($method = 'direct'){
117
118
119 if ( defined('FS_METHOD') ){
120
121 define('WPIDE_FS_METHOD_FORCED_ELSEWHERE', FS_METHOD); //make a note of the forced method
122
123 }else{
124
125 define('FS_METHOD', $method); //force direct
126
127 }
128
129 }
130
131
132 public function hide_wp_sidebar_nav($classes) {
133
134 return str_replace("auto-fold", "", $classes) . ' folded';
135 }
136
137 public function hide_wp_update_nag() {
138 remove_action( 'admin_notices', 'update_nag', 3 );
139 }
140
141 public static function add_admin_nav_warning()
142 {
143 ?>
144 <script type="text/javascript">
145
146 jQuery(document).ready(function($) {
147 window.onbeforeunload = function() {
148 return 'You are attempting to navigate away from WPide. Make sure you have saved any changes made to your files otherwise they will be forgotten.' ;
149 }
150 });
151
152 </script>
153 <?php
154 }
155
156
157
158
159
160
161 public static function add_admin_js(){
162
163 $plugin_path = plugin_dir_url( __FILE__ );
164 //include file tree
165 wp_enqueue_script('jquery-file-tree', plugins_url("jqueryFileTree.js", __FILE__ ) );
166 //include ace
167 wp_enqueue_script('ace', plugins_url("js/ace-1.1.1/ace.js", __FILE__ ) );
168 //include ace modes for css, javascript & php
169 wp_enqueue_script('ace-mode-css', $plugin_path . 'js/ace-1.1.1/mode-css.js');
170 wp_enqueue_script('ace-mode-less', $plugin_path . 'js/ace-1.1.1/mode-less.js');
171 wp_enqueue_script('ace-mode-javascript', $plugin_path . 'js/ace-1.1.1/mode-javascript.js');
172 wp_enqueue_script('ace-mode-php', $plugin_path . 'js/ace-1.1.1/mode-php.js');
173 //include ace theme
174 wp_enqueue_script('ace-theme', plugins_url("js/ace-1.1.1/theme-dawn.js", __FILE__ ) );//ambiance looks really nice for high contrast
175 // wordpress-completion tags
176 wp_enqueue_script('wpide-wordpress-completion', plugins_url("js/autocomplete/wordpress.js", __FILE__ ) );
177 // php-completion tags
178 wp_enqueue_script('wpide-php-completion', plugins_url("js/autocomplete/php.js", __FILE__ ) );
179 // load editor
180 wp_enqueue_script('wpide-load-editor', plugins_url("js/load-editor.js", __FILE__ ) );
181 // load autocomplete dropdown
182 wp_enqueue_script('wpide-dd', plugins_url("js/jquery.dd.js", __FILE__ ) );
183
184 // load jquery ui
185 wp_enqueue_script('jquery-ui', plugins_url("js/jquery-ui-1.9.2.custom.min.js", __FILE__ ), array('jquery'), '1.9.2');
186
187 // load color picker
188 wp_enqueue_script('ImageColorPicker', plugins_url("js/ImageColorPicker.js", __FILE__ ), array('jquery'), '0.3');
189
190
191
192 }
193
194 public static function add_admin_styles(){
195
196 //main wpide styles
197 wp_register_style( 'wpide_style', plugins_url('wpide.css', __FILE__) );
198 wp_enqueue_style( 'wpide_style' );
199 //filetree styles
200 wp_register_style( 'wpide_filetree_style', plugins_url('jqueryFileTree.css', __FILE__) );
201 wp_enqueue_style( 'wpide_filetree_style' );
202 //autocomplete dropdown styles
203 wp_register_style( 'wpide_dd_style', plugins_url('dd.css', __FILE__) );
204 wp_enqueue_style( 'wpide_dd_style' );
205
206 //jquery ui styles
207 wp_register_style( 'wpide_jqueryui_style', plugins_url('css/flick/jquery-ui-1.8.20.custom.css', __FILE__) );
208 wp_enqueue_style( 'wpide_jqueryui_style' );
209
210
211 }
212
213
214
215 public static function jqueryFileTree_get_list() {
216 //check the user has the permissions
217 check_admin_referer('plugin-name-action_wpidenonce');
218 if ( !current_user_can('edit_themes') )
219 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
220
221 //setup wp_filesystem api
222 global $wp_filesystem;
223 $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
224 $form_fields = null; // for now, but at some point the login info should be passed in here
225 if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
226 // no credentials yet, just produced a form for the user to fill in
227 return true; // stop the normal page form from displaying
228 }
229
230 if ( ! WP_Filesystem($creds) )
231 return false;
232
233 $_POST['dir'] = urldecode($_POST['dir']);
234 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
235
236 if( $wp_filesystem->exists($root . $_POST['dir']) ) {
237
238 $files = $wp_filesystem->dirlist($root . $_POST['dir']);
239
240 echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
241 if( count($files) > 0 ) {
242
243 //build seperate arrays for folders and files
244 $dir_array = array();
245 $file_array = array();
246 foreach( $files as $file => $file_info ) {
247 if( $file != '.' && $file != '..' && $file_info['type']=='d' ) {
248 $file_string = strtolower( preg_replace("[._-]", "", $file) );
249 $dir_array[$file_string] = $file_info;
250 }elseif ( $file != '.' && $file != '..' && $file_info['type']=='f' ){
251 $file_string = strtolower( preg_replace("[._-]", "", $file) );
252 $file_array[$file_string] = $file_info;
253 }
254 }
255
256 //shot those arrays
257 ksort($dir_array);
258 ksort($file_array);
259
260 // All dirs
261 foreach( $dir_array as $file => $file_info ) {
262 echo "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file_info['name']) . "/\">" . htmlentities($file_info['name']) . "</a></li>";
263 }
264 // All files
265 foreach( $file_array as $file => $file_info ) {
266 $ext = preg_replace('/^.*\./', '', $file_info['name']);
267 echo "<li class=\"file ext_$ext\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file_info['name']) . "\">" . htmlentities($file_info['name']) . "</a></li>";
268 }
269 }
270 //output toolbar for creating new file, folder etc
271 echo "<li class=\"create_new\"><a class='new_directory' title='Create a new directory here.' href=\"#\" rel=\"{type: 'directory', path: '" . htmlentities($_POST['dir']) . "'}\"></a> <a class='new_file' title='Create a new file here.' href=\"#\" rel=\"{type: 'file', path: '" . htmlentities($_POST['dir']) . "'}\"></a><br style='clear:both;' /></li>";
272 echo "</ul>";
273 }
274
275 die(); // this is required to return a proper result
276 }
277
278
279 public static function wpide_get_file() {
280 //check the user has the permissions
281 check_admin_referer('plugin-name-action_wpidenonce');
282 if ( !current_user_can('edit_themes') )
283 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
284
285 //setup wp_filesystem api
286 global $wp_filesystem;
287 $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
288 $form_fields = null; // for now, but at some point the login info should be passed in here
289 if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
290 // no credentials yet, just produced a form for the user to fill in
291 return true; // stop the normal page form from displaying
292 }
293 if ( ! WP_Filesystem($creds) )
294 return false;
295
296
297 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
298 $file_name = $root . stripslashes($_POST['filename']);
299 echo $wp_filesystem->get_contents($file_name);
300 die(); // this is required to return a proper result
301 }
302
303 public function git_ssh_gen(){
304
305 //errors need to be on while experimental
306 error_reporting(E_ALL);
307 ini_set("display_errors", 1);
308
309 $gitpath = preg_replace("#/$#", "", sanitize_text_field($_POST['sshpath']) );
310
311 //create the folder if doesn't exist
312 if (! file_exists($gitpath) ){
313 mkdir( $gitpath, 0700);
314 }
315
316 //create known hosts if doesn't exist
317 if (! file_exists($gitpath . "/known_hosts") ){
318 touch( $gitpath . "/known_hosts" );
319 chmod( $gitpath . "/known_hosts", 0700 );
320 }
321
322 //create keys if not exist
323 if (! file_exists($gitpath . "/id_rsa") || ! file_exists($gitpath . "/id_rsa.pub") ){
324
325 set_include_path(get_include_path() . PATH_SEPARATOR . plugin_dir_path(__FILE__) . 'git/phpseclib');
326
327 include('Crypt/RSA.php');
328
329 $rsa = new Crypt_RSA();
330
331 $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH);
332
333 extract($rsa->createKey()); // == $rsa->createKey(1024) where 1024 is the key size - $privatekey and $publickey
334
335 //create private key
336 file_put_contents($gitpath . "/id_rsa", $privatekey);
337 chmod( $gitpath . "/id_rsa", 0700 );
338
339 //create public key
340 file_put_contents($gitpath . "/id_rsa.pub", $publickey);
341 chmod( $gitpath . "/id_rsa.pub", 0700 );
342
343 }
344
345 //return public key
346 echo "\n\n". file_get_contents( $gitpath . "/id_rsa.pub" ) ."\n\n";
347
348 die();
349 }
350
351 public function git_open_repo(){
352
353 //errors need to be on while experimental
354 error_reporting(E_ALL);
355 ini_set("display_errors", 1);
356
357 require_once('git/autoload.php.dist');
358
359 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR ) . "/";
360
361 //check repo path entered or die
362 if ( !strlen($_POST['gitpath']) )
363 die("Error: Path to your git repository is required! (see settings)");
364
365
366 $this->git_repo_path = $root . sanitize_text_field( $_POST['gitpath'] );
367 $gitbinary = sanitize_text_field( stripslashes($_POST['gitbinary']) );
368 /*
369 if ( $gitbinary==="I'll guess.." ){ //the binary path
370
371 $thebinary = TQ\Git\Cli\Binary::locateBinary();
372 $this->git = TQ\Git\Repository\Repository::open($this->git_repo_path, new TQ\Git\Cli\Binary( $thebinary ), 0755 );
373
374 }else{
375
376 $thebinary = $_POST['gitbinary'];
377 $this->git = TQ\Git\Repository\Repository::open($this->git_repo_path, new TQ\Git\Cli\Binary( $thebinary ), 0755 );
378
379 }
380 */
381
382 }
383
384 public function git_status() {
385 //check the user has the permissions
386 check_admin_referer('plugin-name-action_wpidenonce');
387 if ( !current_user_can('edit_themes') )
388 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
389
390 $this->git_open_repo(); // make sure git repo is open
391
392 //echo branch
393 $branch = $this->git->getCurrentBranch();
394 echo "<p><strong>Current branch:</strong> " . $branch . "</p>";
395
396 // [0] => Array
397 //(
398 // [file] => WPide.php
399 // [x] =>
400 // [y] => M
401 // [renamed] =>
402 //)
403 $status = $this->git->getStatus();
404 $i=0;//row counter
405 if ( count($status) ){
406
407 //echo out rows of staged files
408 foreach ($status as $item){
409 echo "<div class='gitfilerow ". ($i % 2 != 0 ? "light" : "") ."'><span class='filename'>{$item['file']}</span> <input type='checkbox' name='". str_replace("=", '_', base64_encode($item['file']) ) ."' value='". base64_encode($item['file']) ."' checked />
410 <a href='". base64_encode($item['file']) ."' class='viewdiff'>[view diff]</a> <div class='gitdivdiff ". str_replace("=", '_', base64_encode($item['file']) ) ."'></div> </div>";
411 $i++;
412 }
413 }else{
414 echo "<p class='red'>No changed files in this repo so nothing to commit.</p>";
415 }
416
417 //output the commit message box
418 echo "<div id='gitdivcommit'><label>Commit message</label><br /><input type='text' id='gitmessage' name='message' class='message' />
419 <p><a href='#' class='button-primary'>Commit the staged chanages</a></p></div>";
420
421 die(); // this is required to return a proper result
422 }
423
424
425
426 public function git_log() {
427 //check the user has the permissions
428 check_admin_referer('plugin-name-action_wpidenonce');
429 if ( !current_user_can('edit_themes') )
430 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
431
432 $this->git_open_repo(); // make sure git repo is open
433
434 $log = $this->git->getLog(50);
435
436 echo "<div class='git_log'>";
437 foreach($log as $item){
438 $matches = array();
439 $log_array = array();
440 $bits = explode("\n", $item);
441
442 foreach ($bits as $bit){
443 if ( preg_match_all("#(.*): (.*)#iS", trim($bit), $matches) ){
444
445 $key = $matches[1][0];
446
447 if (is_string($key) && trim($key) !== ""){
448 $log_array[ $key ] = trim( $matches[2][0] );
449 }
450
451 }
452
453 }
454
455 $commit_message = explode( end($log_array), $item);
456 $log_array[ 'message' ] = trim($commit_message[2]);
457
458 $commit = explode( reset($log_array), $item);
459 $log_array[ 'commit' ] = trim( str_replace( array("commit ", "Author:"), "", $commit[0] ) );
460
461
462 echo "<span class='input_row'>";
463 echo "<span class='message'>{$log_array[ 'message' ]}</span> {$log_array[ 'AuthorDate' ]} <span style='float:right;'>ID: {$log_array[ 'commit' ]}</span> ";
464 echo "</span>";
465 }
466 echo "</div>";
467
468
469 die(); // this is required to return a proper result
470 }
471
472
473 public function git_init() {
474 //check the user has the permissions
475 check_admin_referer('plugin-name-action_wpidenonce');
476 if ( !current_user_can('edit_themes') )
477 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
478
479 $this->git_open_repo(); // make sure git repo is open
480
481 //create the local repo path if it doesn't exist
482 if ( !file_exists( $this->git->getRepositoryPath() ) )
483 mkdir( $this->git->getRepositoryPath() );
484
485 $result = $this->git->getBinary()->{'init'}($this->git->getRepositoryPath(), array(
486
487 ));
488
489 //return $result->getStdOut(); //still not getting enough output from the push...
490 if ( $result->getStdErr() === ''){
491
492 echo $result->getStdOut();
493
494 }else{
495 echo $result->getStdErr();
496 }
497
498
499
500
501 die(); // this is required to return a proper result
502 }
503
504
505 public function git_clone() {
506 //check the user has the permissions
507 check_admin_referer('plugin-name-action_wpidenonce');
508 if ( !current_user_can('edit_themes') )
509 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
510
511 $this->git_open_repo(); // make sure git repo is open
512
513 //just incase it's a private repo we will setup the keys
514 $sshpath = preg_replace("#/$#", "", $_POST['sshpath']); //get path replacing end slash if entered
515
516 putenv("GIT_SSH=". plugin_dir_path(__FILE__) . 'git/git-wrapper-nohostcheck.sh'); //tell Git about our wrapper script
517 /* See note on git_push re wrapper */
518 putenv("WPIDE_SSH_PATH=" . $sshpath); //no trailing slash - pass wp-content path to Git wrapper script
519 putenv("HOME=". plugin_dir_path(__FILE__) . 'git'); //no trailing slash - set home to the git directory (this may not be needed)
520
521
522 if ($_POST['repo_path'] === '' || is_null($_POST['repo_path']) ){
523
524 echo "<span class='input_row'>
525 <label>Clone a remote repository by entering it's remote path</label>
526 <input type='text' name='repo_path' id='repo_path' value=''> <em>It will be cloned into the repository path/folder defined in the Git settings.</em>
527 <p><a href='#' class='button-primary git_clone'>Clone</a></p>
528 </span>";
529 die();
530
531 }
532
533 $path = sanitize_text_field( $_POST['repo_path'] );
534
535 //create the local repo path if it doesn't exist
536 if ( !file_exists( $this->git->getRepositoryPath() ) )
537 mkdir( $this->git->getRepositoryPath() );
538
539 $result = $this->git->getBinary()->{'clone'}($this->git->getRepositoryPath(), array(
540 $path,
541 $this->git->getRepositoryPath(),
542 '--recursive'
543 ));
544
545 //return $result->getStdOut(); //still not getting enough output from the push...
546 if ( $result->getStdErr() === ''){
547
548 $result = $result->getStdOut();
549
550 //format the output a little better
551 $result = str_replace('...', '...<br />', $result);
552
553 echo $result;
554
555 }else{
556 echo $result->getStdErr();
557 }
558
559
560
561
562 die(); // this is required to return a proper result
563 }
564
565 public function git_push() {
566 //check the user has the permissions
567 check_admin_referer('plugin-name-action_wpidenonce');
568 if ( !current_user_can('edit_themes') )
569 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
570
571 $this->git_open_repo(); // make sure git repo is open
572
573 $sshpath = preg_replace("#/$#", "", $_POST['sshpath']); //get path replacing end slash if entered
574
575 putenv("GIT_SSH=". plugin_dir_path(__FILE__) . 'git/git-wrapper-nohostcheck.sh'); //tell Git about our wrapper script
576 /*
577 The wrapper we use above doesn't do a host check which means we can't guarentee the other side is who we think it is
578 We have this other wrapper which does a host check which we should swap to after the initial push/connection has been made
579 and the entry automatically added to known hosts but that logic isn't in place yet.
580 putenv("GIT_SSH=". plugin_dir_path(__FILE__) . 'git/git-wrapper.sh');
581 */
582 putenv("WPIDE_SSH_PATH=" . $sshpath); //no trailing slash - pass wp-content path to Git wrapper script
583 putenv("HOME=". plugin_dir_path(__FILE__) . 'git'); //no trailing slash - set home to the git directory (this may not be needed)
584
585 echo "<pre>";
586 $push_result = $this->git->push( );
587 echo "</pre>";
588
589 if ($push_result === ''){
590 echo "Sucessfully pushed to your remote repo";
591 }else{
592 echo $push_result;
593 }
594
595 echo "<p>Git push completed.</p>";
596
597 die(); // this is required to return a proper result
598 }
599
600
601 public function git_diff() {
602 //check the user has the permissions
603 check_admin_referer('plugin-name-action_wpidenonce');
604 if ( !current_user_can('edit_themes') )
605 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
606
607 $this->git_open_repo(); // make sure git repo is open
608
609 $file = sanitize_text_field( base64_decode( $_POST['file']) );
610
611 $result = $this->git->getBinary()->{'diff'}($this->git->getRepositoryPath(), array(
612 $file
613 ));
614
615 //return $result->getStdOut(); //still not getting enough output from the push...
616 if ( $result->getStdErr() === ''){
617
618 $diff_lines = explode("\n", $result->getStdOut() );
619 foreach ($diff_lines as $a_line){
620 if ( preg_match("#^\+#", $a_line) ){
621 $a_class = 'plus';
622 }elseif ( preg_match("#^\-#", $a_line) ) {
623 $a_class = 'minus';
624 }else{
625 $a_class = '';
626 }
627 echo "<span class='diff_line {$a_class}'>{$a_line}</span>";
628 }
629
630 }else{
631 echo $result->getStdErr();
632 }
633
634 echo "<strong>Diff</strong>" . $diff_table;
635
636
637 die(); // this is required to return a proper result
638 }
639
640
641 public function git_commit() {
642 //check the user has the permissions
643 check_admin_referer('plugin-name-action_wpidenonce');
644 if ( !current_user_can('edit_themes') )
645 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
646
647 $this->git_open_repo(); // make sure git repo is open
648
649 //putenv("GIT_AUTHOR_NAME=WPsites"); //author can be set using env but for now we set it during the commit
650 //putenv("GIT_AUTHOR_EMAIL=simon@wpsites.co.uk");
651 putenv("GIT_COMMITTER_NAME=WPide"); //commiter details, shows under author on github
652 putenv("GIT_COMMITTER_EMAIL=wpide@wpide.co.uk");
653
654 $files = array();
655 foreach ($_POST['files'] as $file){
656 $files[] = base64_decode( $file );
657 }
658
659 //get the current user to be used for the commit
660 $current_user = wp_get_current_user();
661
662 $this->git->add( $files );
663 $this->git->commit( sanitize_text_field( stripslashes($_POST['gitmessage']) ) , $files, "{$current_user->user_firstname} {$current_user->user_lastname} <{$current_user->user_email}>");
664
665 wpide::git_status();
666
667 die(); // this is required to return a proper result
668 }
669
670
671 public static function wpide_image_edit_key() {
672
673 //check the user has the permissions
674 check_admin_referer('plugin-name-action_wpidenonce');
675 if ( !current_user_can('edit_themes') )
676 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
677
678 //create a nonce based on the image path
679 echo wp_create_nonce( 'wpide_image_edit' . $_POST['file'] );
680
681 }
682
683 public static function wpide_create_new() {
684 //check the user has the permissions
685 check_admin_referer('plugin-name-action_wpidenonce');
686 if ( !current_user_can('edit_themes') )
687 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
688
689 //setup wp_filesystem api
690 global $wp_filesystem;
691 $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
692 $form_fields = null; // for now, but at some point the login info should be passed in here
693 if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
694 // no credentials yet, just produced a form for the user to fill in
695 return true; // stop the normal page form from displaying
696 }
697 if ( ! WP_Filesystem($creds) )
698 return false;
699
700 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
701
702 //check all required vars are passed
703 if (strlen($_POST['path'])>0 && strlen($_POST['type'])>0 && strlen($_POST['file'])>0){
704
705
706 $filename = sanitize_file_name( $_POST['file'] );
707 $path = $_POST['path'];
708
709 if ($_POST['type'] == "directory"){
710
711 $write_result = $wp_filesystem->mkdir($root . $path . $filename, FS_CHMOD_DIR);
712
713 if ($write_result){
714 die("1"); //created
715 }else{
716 echo "Problem creating directory" . $root . $path . $filename;
717 }
718
719 }else if ($_POST['type'] == "file"){
720
721 //write the file
722 $write_result = $wp_filesystem->put_contents(
723 $root . $path . $filename,
724 '',
725 FS_CHMOD_FILE // predefined mode settings for WP files
726 );
727
728 if ($write_result){
729 die("1"); //created
730 }else{
731 echo "Problem creating file " . $root . $path . $filename;
732 }
733
734 }
735
736
737 //print_r($_POST);
738
739
740 }
741 echo "0";
742 die(); // this is required to return a proper result
743 }
744
745 public static function wpide_save_file() {
746 //check the user has the permissions
747 check_admin_referer('plugin-name-action_wpidenonce');
748 if ( !current_user_can('edit_themes') )
749 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
750
751 $is_php = false;
752
753 //check file syntax of PHP files by parsing the PHP
754 if ( preg_match("#\.php$#i", $_POST['filename']) ){
755
756 $is_php = true;
757
758 require('PHP-Parser/lib/bootstrap.php');
759 ini_set('xdebug.max_nesting_level', 2000);
760
761 $code = stripslashes($_POST['content']);
762
763 $parser = new PHPParser_Parser(new PHPParser_Lexer);
764
765 try {
766 $stmts = $parser->parse($code);
767 } catch (PHPParser_Error $e) {
768 echo 'Parse Error: ', $e->getMessage();
769 die();
770 }
771 }
772
773 //setup wp_filesystem api
774 global $wp_filesystem;
775 $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
776 $form_fields = null; // for now, but at some point the login info should be passed in here
777 if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
778 // no credentials yet, just produced a form for the user to fill in
779 return true; // stop the normal page form from displaying
780 }
781 if ( ! WP_Filesystem($creds) )
782 echo "Cannot initialise the WP file system API";
783
784 //save a copy of the file and create a backup just in case
785 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
786 $file_name = $root . stripslashes($_POST['filename']);
787
788 //set backup filename
789 $backup_path = 'backups' . preg_replace( "#\.php$#i", "_".date("Y-m-d-H").".php", $_POST['filename'] );
790 $backup_path_full = plugin_dir_path(__FILE__) . $backup_path;
791 //create backup directory if not there
792 $new_file_info = pathinfo($backup_path_full);
793 if (!$wp_filesystem->is_dir($new_file_info['dirname'])) wp_mkdir_p( $new_file_info['dirname'] ); //should use the filesytem api here but there isn't a comparable command right now
794
795
796
797 if ($is_php){
798 //create the backup file adding some php to the file to enable direct restore
799 global $current_user;
800 get_currentuserinfo();
801 $user_md5 = md5( serialize($current_user) );
802
803 $restore_php = '<?php /* start WPide restore code */
804 if ($_POST["restorewpnonce"] === "'. $user_md5.$_POST['_wpnonce'] .'"){
805 if ( file_put_contents ( "'.$file_name.'" , preg_replace("#<\?php /\* start WPide(.*)end WPide restore code \*/ \?>#s", "", file_get_contents("'.$backup_path_full.'") ) ) ){
806 echo "Your file has been restored, overwritting the recently edited file! \n\n The active editor still contains the broken or unwanted code. If you no longer need that content then close the tab and start fresh with the restored file.";
807 }
808 }else{
809 echo "-1";
810 }
811 die();
812 /* end WPide restore code */ ?>';
813
814 file_put_contents ( $backup_path_full , $restore_php . file_get_contents($file_name) );
815
816 }else{
817 //do normal backup
818 $wp_filesystem->copy( $file_name, $backup_path_full );
819 }
820
821 //save file
822 if( $wp_filesystem->put_contents( $file_name, stripslashes($_POST['content'])) ) {
823
824 //lets create an extra long nonce to make it less crackable
825 global $current_user;
826 get_currentuserinfo();
827 $user_md5 = md5( serialize($current_user) );
828
829 $result = "\"". $backup_path . ":::" . $user_md5 ."\"";
830 }
831
832 die($result); // this is required to return a proper result
833 }
834
835 public static function wpide_save_image() {
836
837 $filennonce = split("::", $_POST["opt"]); //file::nonce
838
839 //check the user has a valid nonce
840 //we are checking two variations of the nonce, one as-is and another that we have removed a trailing zero from
841 //this is to get around some sort of bug where a nonce generated on another page has a trailing zero and a nonce generated/checked here doesn't have the zero
842 if (! wp_verify_nonce( $filennonce[1], 'wpide_image_edit' . $filennonce[0]) &&
843 ! wp_verify_nonce( rtrim($filennonce[1], "0") , 'wpide_image_edit' . $filennonce[0])) {
844 die('Security check'); //die because both checks failed
845 }
846 //check the user has the permissions
847 if ( !current_user_can('edit_themes') )
848 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
849
850
851 $_POST['content'] = base64_decode($_POST["data"]); //image content
852 $_POST['filename'] = $filennonce[0]; //filename
853
854 //setup wp_filesystem api
855 global $wp_filesystem;
856 $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
857 $form_fields = null; // for now, but at some point the login info should be passed in here
858 if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
859 // no credentials yet, just produced a form for the user to fill in
860 return true; // stop the normal page form from displaying
861 }
862 if ( ! WP_Filesystem($creds) )
863 echo "Cannot initialise the WP file system API";
864
865 //save a copy of the file and create a backup just in case
866 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
867 $file_name = $root . stripslashes($_POST['filename']);
868
869 //set backup filename
870 $backup_path = 'backups' . preg_replace( "#\.php$#i", "_".date("Y-m-d-H").".php", $_POST['filename'] );
871 $backup_path = plugin_dir_path(__FILE__) . $backup_path;
872
873 //create backup directory if not there
874 $new_file_info = pathinfo($backup_path);
875 if (!$wp_filesystem->is_dir($new_file_info['dirname'])) wp_mkdir_p( $new_file_info['dirname'] ); //should use the filesytem api here but there isn't a comparable command right now
876
877 //do backup
878 $wp_filesystem->move( $file_name, $backup_path );
879
880
881 //save file
882 if( $wp_filesystem->put_contents( $file_name, $_POST['content']) ) {
883 $result = "success";
884 }
885
886 if ($result == "success"){
887 wp_die('<p>'.__('<strong>Image saved.</strong> <br />You may <a href="JavaScript:window.close();">close this window / tab</a>.').'</p>');
888 }else{
889 wp_die('<p>'.__('<strong>Problem saving image.</strong> <br /><a href="JavaScript:window.close();">Close this window / tab</a> and try editing the image again.').'</p>');
890 }
891 //print_r($_POST);
892
893
894 //return;
895 }
896
897
898 public static function wpide_startup_check() {
899 global $wp_filesystem, $wp_version;
900
901 echo "\n\n\n\nWPIDE STARTUP CHECKS \n";
902 echo "___________________ \n\n";
903
904 //WordPress version
905 if ($wp_version > 3){
906 echo "WordPress version = " . $wp_version . "\n\n";
907 }else{
908 echo "WordPress version = " . $wp_version . " (which is too old to run WPide) \n\n";
909 }
910
911 //check the user has the permissions
912 check_admin_referer('plugin-name-action_wpidenonce');
913 if ( !current_user_can('edit_themes') )
914 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
915
916 if ( defined( 'WPIDE_FS_METHOD_FORCED_ELSEWHERE' ) ){
917 echo "WordPress filesystem API has been forced to use the " . WPIDE_FS_METHOD_FORCED . " method by another plugin/WordPress. \n\n";
918 }
919
920 //setup wp_filesystem api
921 $wpide_filesystem_before = $wp_filesystem;
922
923 $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
924 $form_fields = null; // for now, but at some point the login info should be passed in here
925 ob_start();
926 if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
927 // if we get here, then we don't have credentials yet,
928 // but have just produced a form for the user to fill in,
929 // so stop processing for now
930 //return true; // stop the normal page form from displaying
931 }
932 ob_end_clean();
933 if ( ! WP_Filesystem($creds) ) {
934
935 echo "There has been a problem initialising the filesystem API \n\n";
936 echo "Filesystem API before this plugin ran: \n\n" . print_r($wpide_filesystem_before, true);
937 echo "Filesystem API now: \n\n" . print_r($wp_filesystem, true);
938
939 }
940 unset($wpide_filesystem_before);
941
942
943 $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
944 if ( isset($wp_filesystem) ){
945
946 //Running webservers user and group
947 echo "Web server user/group = " . getenv('APACHE_RUN_USER') . ":" . getenv('APACHE_RUN_GROUP') . "\n";
948 //wp-content user and group
949 echo "wp-content owner/group = " . $wp_filesystem->owner( $root ) . ":" . $wp_filesystem->group( $root ) . "\n\n";
950
951
952 //check we can list wp-content files
953 if( $wp_filesystem->exists( $root ) ){
954
955 $files = $wp_filesystem->dirlist( $root );
956 if ( count($files) > 0){
957 echo "wp-content folder exists and contains ". count($files) ." files \n";
958 }else{
959 echo "wp-content folder exists but we cannot read it's contents \n";
960 }
961 }
962
963 // $wp_filesystem->owner() $wp_filesystem->group() $wp_filesystem->is_writable() $wp_filesystem->is_readable()
964 echo "\nUsing the ".$wp_filesystem->method." method of the WP filesystem API\n";
965
966 //wp-content editable?
967 echo "The wp-content folder ". ( $wp_filesystem->is_readable( $root )==1 ? "IS":"IS NOT" ) ." readable and ". ( $wp_filesystem->is_writable( $root )==1 ? "IS":"IS NOT" ) ." writable by this method \n";
968
969
970 //plugins folder editable
971 echo "The wp-content/plugins folder ". ( $wp_filesystem->is_readable( $root."/plugins" )==1 ? "IS":"IS NOT" ) ." readable and ". ( $wp_filesystem->is_writable( $root."/plugins" )==1 ? "IS":"IS NOT" ) ." writable by this method \n";
972
973
974 //themes folder editable
975 echo "The wp-content/themes folder ". ( $wp_filesystem->is_readable( $root."/themes" )==1 ? "IS":"IS NOT" ) ." readable and ". ( $wp_filesystem->is_writable( $root."/themes" )==1 ? "IS":"IS NOT" ) ." writable by this method \n";
976
977 }
978
979 echo "___________________ \n\n\n\n";
980
981 echo " If the file tree to the right is empty there is a possibility that your server permissions are not compatible with this plugin. \n The startup information above may shed some light on things. \n Paste that information into the support forum for further assistance.";
982
983
984 die();
985
986 }
987
988
989
990
991 public function add_my_menu_page() {
992 //add_menu_page("wpide", "wpide","edit_themes", "wpidesettings", array( &$this, 'my_menu_page') );
993 add_menu_page('WPide', 'WPide', 'edit_themes', "wpide", array( &$this, 'my_menu_page' ));
994 }
995
996 public function my_menu_page() {
997 if ( !current_user_can('edit_themes') )
998 wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
999
1000 $app_url = get_bloginfo('url'); //need to make this https if we are currently looking on the site using https (even though https for admin might not be forced it can still cause issues)
1001 if (is_ssl()) $app_url = str_replace("http:", "https:", $app_url);
1002
1003 ?>
1004 <script>
1005
1006 var wpide_app_path = "<?php echo plugin_dir_url( __FILE__ ); ?>";
1007 //dont think this is needed any more.. var wpide_file_root_url = "<?php echo apply_filters("wpide_file_root_url", WP_CONTENT_URL );?>";
1008 var user_nonce_addition = '';
1009
1010 function the_filetree() {
1011 jQuery('#wpide_file_browser').fileTree({ script: ajaxurl }, function(parent, file) {
1012
1013 if ( jQuery(parent).hasClass("create_new") ){ //create new file/folder
1014 //to create a new item we need to know the name of it so show input
1015
1016 var item = eval('('+file+')');
1017
1018 //hide all inputs just incase one is selected
1019 jQuery(".new_item_inputs").hide();
1020 //show the input form for this
1021 jQuery("div.new_" + item.type).show();
1022 jQuery("div.new_" + item.type + " input[name='new_" + item.type + "']").focus();
1023 jQuery("div.new_" + item.type + " input[name='new_" + item.type + "']").attr("rel", file);
1024
1025
1026 }else if ( jQuery(".wpide_tab[rel='"+file+"']").length > 0) { //focus existing tab
1027 jQuery(".wpide_tab[sessionrel='"+ jQuery(".wpide_tab[rel='"+file+"']").attr("sessionrel") +"']").click();//focus the already open tab
1028 }else{ //open file
1029
1030 var image_patern =new RegExp("(\.jpg|\.gif|\.png|\.bmp)");
1031 if ( image_patern.test(file) ){
1032 //it's an image so open it for editing
1033
1034 //using modal+iframe
1035 if ("lets not" == "use the modal for now"){
1036
1037 var NewDialog = jQuery('<div id="MenuDialog">\
1038 <iframe src="http://www.sumopaint.com/app/?key=ebcdaezjeojbfgih&target=<?php echo get_bloginfo('url') . "?action=wpide_image_save";?>&url=<?php echo get_bloginfo('url') . "/wp-content";?>' + file + '&title=Edit image&service=Save back to WPide" width="100%" height="600px"> </iframe>\
1039 </div>');
1040 NewDialog.dialog({
1041 modal: true,
1042 title: "title",
1043 show: 'clip',
1044 hide: 'clip',
1045 width:'800',
1046 height:'600'
1047 });
1048
1049 }else{ //open in new tab/window
1050
1051 var data = { action: 'wpide_image_edit_key', file: file, _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val() };
1052 var image_data = '';
1053 jQuery.ajaxSetup({async:false}); //we need to wait until we get the response before opening the window
1054 jQuery.post(ajaxurl, data, function(response) {
1055
1056 //with the response (which is a nonce), build the json data to pass to the image editor. The edit key (nonce) is only valid to edit this image
1057 image_data = file+'::'+response;
1058
1059 });
1060
1061 jQuery.ajaxSetup({async:true});//enable async again
1062
1063
1064 window.open('http://www.sumopaint.com/app/?key=ebcdaezjeojbfgih&url=<?php echo $app_url. "/wp-content";?>' + file + '&opt=' + image_data + '&title=Edit image&service=Save back to WPide&target=<?php echo urlencode( $app_url . "/wp-admin/admin.php?wpide_save_image=yes" ) ;?>');
1065
1066 }
1067
1068 }else{
1069 jQuery(parent).addClass('wait');
1070
1071 wpide_set_file_contents(file, function(){
1072
1073 //once file loaded remove the wait class/indicator
1074 jQuery(parent).removeClass('wait');
1075
1076 });
1077
1078 jQuery('#filename').val(file);
1079 }
1080
1081 }
1082
1083 });
1084 }
1085
1086
1087
1088 jQuery(document).ready(function($) {
1089
1090 $("#fancyeditordiv").css("height", ($('body').height()-120) + 'px' );
1091
1092 //set up the git commit overlay
1093 $('#gitdiv').dialog({
1094 autoOpen: false,
1095 title: 'Git',
1096 width: 800
1097 });
1098
1099 // Handler for .ready() called.
1100 the_filetree() ;
1101
1102 //inialise the color assist
1103 $("#wpide_color_assist img").ImageColorPicker({
1104 afterColorSelected: function(event, color){
1105 jQuery("#wpide_color_assist_input").val(color);
1106 }
1107 });
1108 $("#wpide_color_assist").hide(); //hide it until it's needed
1109
1110 $("#wpide_color_assist_send").click(function(e){
1111 e.preventDefault();
1112 editor.insert( jQuery("#wpide_color_assist_input").val().replace('#', '') );
1113
1114 $("#wpide_color_assist").hide(); //hide it until it's needed again
1115 });
1116
1117 $(".close_color_picker a").click(function(e){
1118 e.preventDefault();
1119 $("#wpide_color_assist").hide(); //hide it until it's needed again
1120 });
1121
1122 $("#wpide_toolbar_buttons").on('click', "a.restore", function(e){
1123 e.preventDefault();
1124 var file_path = jQuery(".wpide_tab.active", "#wpide_toolbar").data( "backup" );
1125
1126 jQuery("#wpide_message").hide(); //might be shortly after a save so a message may be showing, which we don't need
1127 jQuery("#wpide_message").html('<span><strong>File available for restore</strong><p> ' + file_path + '</p><a class="button red restore now" href="'+ wpide_app_path + file_path +'">Restore this file now &#10012;</a><a class="button restore cancel" href="#">Cancel &#10007;</a><br /><em class="note"><strong>note: </strong>You can browse all file backups if you navigate to the backups folder (plugins/WPide/backups/..) using the filetree.</em></span>');
1128 jQuery("#wpide_message").show();
1129 });
1130 $("#wpide_toolbar_buttons").on('click', "a.restore.now", function(e){
1131 e.preventDefault();
1132
1133 var data = { restorewpnonce: user_nonce_addition + jQuery('#_wpnonce').val() };
1134 jQuery.post( wpide_app_path + jQuery(".wpide_tab.active", "#wpide_toolbar").data( "backup" )
1135 , data, function(response) {
1136
1137 if (response == -1){
1138 alert("Problem restoring file.");
1139 }else{
1140 alert( response);
1141 jQuery("#wpide_message").hide();
1142 }
1143
1144 });
1145
1146 });
1147 $("#wpide_toolbar_buttons" ).on('click', "a.cancel", function(e){
1148 e.preventDefault();
1149
1150 jQuery("#wpide_message").hide(); //might be shortly after a save so a message may be showing, which we don't need
1151 });
1152
1153
1154
1155 $("#wpide_git" ).on('click', function(e){
1156 e.preventDefault();
1157
1158 $('#gitdiv').dialog( "open" );
1159
1160 });
1161
1162 $("#gitdiv .show_changed_files" ).on('click', function(e){
1163 e.preventDefault();
1164
1165 $(".git_settings_panel").hide();
1166
1167 var data = { action: 'wpide_git_status', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1168 gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1169
1170 jQuery.post(ajaxurl, data, function(response) {
1171
1172 $("#gitdivcontent").html( response );
1173
1174 });
1175
1176 });
1177
1178
1179 //view chosen diff
1180 $("#gitdiv" ).on('click', ".viewdiff", function(e){
1181 e.preventDefault();
1182
1183 $(".git_settings_panel").hide();
1184
1185 if ( $(this).text() == '[hide diff]'){
1186 $(this).text('[show diff]');
1187 $(this).parent().find(".gitdivdiff").hide();
1188 }else{
1189 $(this).text('[hide diff]');
1190 $(this).parent().find(".gitdivdiff").show();
1191 }
1192
1193 var base64_file = jQuery(this).attr('href');
1194 var data = { action: 'wpide_git_diff', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1195 file: base64_file, gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1196
1197 jQuery.post(ajaxurl, data, function(response) {
1198
1199 $(".gitdivdiff."+ base64_file.replace(/=/g, '_' ) ).html( response );
1200
1201 });
1202
1203 });
1204
1205 //commit selected files
1206 $("#gitdiv" ).on('click', "#gitdivcommit a.button-primary", function(e){
1207 e.preventDefault();
1208
1209 $(".git_settings_panel").hide();
1210
1211 if ( jQuery(".gitfilerow input:checked").length > 0 ){
1212 var files_for_commit = [];
1213 jQuery(".gitfilerow input:checked").each(function( index ) {
1214 files_for_commit[index] = $(this).val();
1215 });
1216 }else{
1217 alert("You haven't selected any files to be committed!");
1218 return;
1219 }
1220
1221 var data = { action: 'wpide_git_commit', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1222 files: files_for_commit, gitmessage: jQuery('#gitmessage').val(), gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1223
1224 jQuery.post(ajaxurl, data, function(response) {
1225
1226 $("#gitdivcontent").html( response );
1227
1228 });
1229
1230 });
1231
1232 //git log
1233 $("#gitdiv" ).on('click', ".git_log", function(e){
1234 e.preventDefault();
1235
1236 $(".git_settings_panel").hide();
1237
1238 var base64_file = jQuery(this).attr('href');
1239 var data = { action: 'wpide_git_log', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1240 sshpath: jQuery('#sshpath').val(), gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1241
1242 jQuery.post(ajaxurl, data, function(response) {
1243
1244 $("#gitdivcontent").html( response );
1245
1246 });
1247
1248 });
1249
1250 //git init
1251 $("#gitdiv" ).on('click', ".git_init", function(e){
1252 e.preventDefault();
1253
1254 $(".git_settings_panel").hide();
1255
1256 var data = { action: 'wpide_git_init', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1257 repo_path: jQuery('#repo_path').val(), gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1258
1259 jQuery.post(ajaxurl, data, function(response) {
1260
1261 $("#gitdivcontent").html( response );
1262
1263 });
1264
1265 });
1266
1267 //git clone
1268 $("#gitdiv" ).on('click', ".git_clone", function(e){
1269 e.preventDefault();
1270
1271 $(".git_settings_panel").hide();
1272
1273 var data = { action: 'wpide_git_clone', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1274 repo_path: jQuery('#repo_path').val(), sshpath: jQuery('#sshpath').val(), gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1275
1276 jQuery.post(ajaxurl, data, function(response) {
1277
1278 $("#gitdivcontent").html( response );
1279
1280 });
1281
1282 });
1283
1284 //git push
1285 $("#gitdiv" ).on('click', ".git_push", function(e){
1286 e.preventDefault();
1287
1288 $(".git_settings_panel").hide();
1289
1290 var data = { action: 'wpide_git_push', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1291 sshpath: jQuery('#sshpath').val(), gitpath: jQuery('#gitpath').val(), gitbinary: jQuery('#gitbinary').val() };
1292
1293 jQuery.post(ajaxurl, data, function(response) {
1294
1295 $("#gitdivcontent").html( response );
1296
1297 });
1298
1299 });
1300
1301 //git show settings
1302 $("#gitdiv" ).on('click', ".git_settings", function(e){
1303 e.preventDefault();
1304 $(".git_settings_panel").toggle();
1305
1306 });
1307
1308
1309 //git SSH key gen/view
1310 $("#gitdiv" ).on('click', ".git_ssh_gen", function(e){
1311 e.preventDefault();
1312
1313 var data = { action: 'wpide_git_ssh_gen', _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val(),
1314 sshpath: jQuery('#sshpath').val() };
1315
1316 jQuery.post(ajaxurl, data, function(response) {
1317
1318 alert("Your SSH key is: "+ response);
1319
1320 });
1321
1322 });
1323
1324
1325
1326 });
1327 </script>
1328
1329
1330
1331 <div id="poststuff" class="metabox-holder has-right-sidebar">
1332
1333 <div id="side-info-column" class="inner-sidebar">
1334
1335 <div id="wpide_info">
1336 <div id="wpide_info_content"></div>
1337 </div>
1338 <br style="clear:both;" />
1339 <div id="wpide_color_assist">
1340 <div class="close_color_picker"><a href="close-color-picker">x</a></div>
1341 <h3>Colour Assist</h3>
1342 <img src='<?php echo plugins_url("images/color-wheel.png", __FILE__ ); ?>' />
1343 <input type="button" class="button" id="wpide_color_assist_send" value="&lt; Send to editor" />
1344 <input type="text" id="wpide_color_assist_input" name="wpide_color_assist_input" value="" />
1345
1346 </div>
1347
1348
1349
1350 <div id="submitdiv" class="postbox ">
1351 <h3 class="hndle"><span>Files</span></h3>
1352 <div class="inside">
1353 <div class="submitbox" id="submitpost">
1354 <div id="minor-publishing">
1355 </div>
1356 <div id="major-publishing-actions">
1357 <div id="wpide_file_browser"></div>
1358 <br style="clear:both;" />
1359 <div class="new_file new_item_inputs">
1360 <label for="new_folder">File name</label><input class="has_data" name="new_file" type="text" rel="" value="" placeholder="Filename.ext" />
1361 <a href="#" id="wpide_create_new_file" class="button-primary">CREATE</a>
1362 </div>
1363 <div class="new_directory new_item_inputs">
1364 <label for="new_directory">Directory name</label><input class="has_data" name="new_directory" type="text" rel="" value="" placeholder="Filename.ext" />
1365 <a href="#" id="wpide_create_new_directory" class="button-primary">CREATE</a>
1366 </div>
1367 <div class="clear"></div>
1368 </div>
1369 </div>
1370 </div>
1371 </div>
1372
1373
1374 </div>
1375
1376 <div id="post-body">
1377 <div id="wpide_toolbar" class="quicktags-toolbar">
1378 <div id="wpide_toolbar_tabs"> </div>
1379 <div id="dialog_window_minimized_container"></div>
1380 </div>
1381
1382 <div id="wpide_toolbar_buttons">
1383 <div id="wpide_message"></div>
1384 <a class="button restore" style="display:none;" title="Restore the active tab" href="#">Restore &#10012;</a>
1385
1386 </div>
1387
1388
1389 <div id='fancyeditordiv'></div>
1390
1391 <form id="wpide_save_container" action="" method="get">
1392 <div id="wpide_footer_message"></div>
1393 <div id="wpide_footer_message_last_saved"></div>
1394 <div id="wpide_footer_message_unsaved"></div>
1395
1396 <a href="#" id="wpide_save" alt="Keyboard shortcut to save [Ctrl/Cmd + S]" title="Keyboard shortcut to save [Ctrl/Cmd + S]" class="button-primary">SAVE
1397 FILE</a>
1398
1399 <a href="#" style="display:none;" id="wpide_git" alt="Open the Git overlay" title="Open the Git overlay" class="button-secondary">Git</a>
1400
1401
1402 <input type="hidden" id="filename" name="filename" value="" />
1403 <?php
1404 if ( function_exists('wp_nonce_field') )
1405 wp_nonce_field('plugin-name-action_wpidenonce');
1406 ?>
1407 </form>
1408
1409 <div id="gitdiv">
1410 <a class="button git_settings" href="#">GIT SETTINGS <em>setting local repo location, keys etc</em></a>
1411 <a class="button git_clone" href="#">GIT CLONE <em>create or clone a repo</em></a>
1412 <a class="button show_changed_files" href="#">GIT STATUS <em>show changed/staged files</em></a>
1413 <a class="button git_log" href="#">GIT LOG <em>history of commits</em></a>
1414 <a class="button git_push" href="#">GIT PUSH <em>push to remote repo</em></a>
1415
1416 <div class="git_settings_panel" style="display:none;">
1417 <h2>Git Settings</h2>
1418 <span class="input_row">
1419 <label>Local repository path</label>
1420 <input type="text" name="gitpath" id="gitpath" value="" />
1421 <em>
1422 The Git repository you want to work with. <br />
1423 If it doesn't exist you can <a href="#" class="red git_init">initiate a blank repository by clicking here</a> or you can <a href="#" class="red git_clone">clone a remote repo over here</a>
1424 </em>
1425 </span>
1426 <span class="input_row">
1427 <label>Git binary</label>
1428 <input type="text" name="gitbinary" id="gitbinary" value="I'll guess.." /> <em>Full path to the local Git binary on this server.</em>
1429 </span>
1430 <span class="input_row">
1431 <label>SSH key path</label>
1432 <input type="text" name="sshpath" id="sshpath" value="<?php echo WP_CONTENT_DIR . '/ssh';?>" /> <em>Full path to the folder that contains your SSH keys (both id_rsa and id_rsa.pub) and a known_hosts file.</em>
1433 </span>
1434 <span class="input_row">
1435 <a href="#" class="git_ssh_gen red">Click here to view your SSH key</a>. If an SSH key cannot be found in the SSH path specified above, WPide will create this key for you. You'll need to pass this key to github or any other services/servers you need Git push access to.
1436 </span>
1437 </div>
1438
1439 <div id="gitdivcontent">
1440 <h2>Git functionality is currently experimental, so use at your own risk</h2>
1441 <p>Saying that, it does work. You can create new Git repositories, clone from remote repositories, push to remote repositories etc. <strong>BUT</strong> there are many Git features missing, errors aren't very tidy and the interface needs some serious attention but I just wanted to get it out there! </p>
1442 <p>For this functionality to work your Git binary needs to be accessible to the web server process/user and that user will probably need an ssh folder in the default place (~/.ssh) otherwise you will have trouble with remote repository access due to the SSH keys</p>
1443 <p>WPide will use it's own SSH key in a custom location which can then even be shared between different WordPress/WPide installs on the same server providing the SSH folder you set in settings is accessible to all installs.</p>
1444 <p>Don't be afraid to close this overlay. It will be in exactly the same state once you press the Git button again.</p>
1445 </div>
1446 </div>
1447 </div>
1448
1449
1450
1451 </div>
1452
1453 <?php
1454 }
1455
1456 }
1457
1458 $wpide = new wpide();
1459
1460 endif; // class_exists check
1461
1462 ?>
1463