diff --git a/.distignore b/.distignore index 5d5a9537..b4b866f6 100644 --- a/.distignore +++ b/.distignore @@ -9,4 +9,10 @@ phpcs.xml node_modules logs package.json -npm-debug.log \ No newline at end of file +bin +tests +phpunit.xml +npm-debug.log +dist +artifact +composer diff --git a/.gitignore b/.gitignore index 5e33a55d..c0e388cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ .idea node_modules logs - +dist +artifact +vendor +composer.lock \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d45a618b..9b23b564 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: php - -## PHP versions to test against php: - "7.0" - "5.6" @@ -9,37 +7,58 @@ php: - "5.3" - "5.2" sudo: false +branches: + except: + - "/^*-v[0-9]/" env: - - WP_VERSION=master WP_MULTISITE=0 + matrix: + - WP_VERSION=latest WP_MULTISITE=0 + global: + - MASTER_BRANCH=production UPSTREAM_REPO=Codeinwp/visualizer STORE_URL=https://themeisle.com install: - - . $HOME/.nvm/nvm.sh - - nvm install stable - - nvm use stable - - npm install - - npm install grunt-cli -g -before_script: - ## Install the wordpress latest version - - export WP_DEVELOP_DIR=/tmp/wordpress/ - - mkdir -p $WP_DEVELOP_DIR - - git clone --depth=1 --branch="$WP_VERSION" git://develop.git.wordpress.org/ $WP_DEVELOP_DIR - - plugin_slug=$(basename $(pwd)) - - plugin_dir=$WP_DEVELOP_DIR/src/wp-content/plugins/$plugin_slug - - cd .. - - mv $plugin_slug $plugin_dir - - cd $WP_DEVELOP_DIR - - cp wp-tests-config-sample.php wp-tests-config.php - - sed -i "s/youremptytestdbnamehere/wordpress_test/" wp-tests-config.php - - sed -i "s/yourusernamehere/root/" wp-tests-config.php - - sed -i "s/yourpasswordhere//" wp-tests-config.php - - mysql -e 'CREATE DATABASE wordpress_test;' -uroot - - ## install PHPCS and Wordpress standards - - pear install pear/PHP_CodeSniffer - - mkdir wordpress-coding-standards && curl -L https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/archive/master.tar.gz | tar xz --strip-components=1 -C wordpress-coding-standards - - phpenv rehash - - phpcs --config-set installed_paths $WP_DEVELOP_DIR/wordpress-coding-standards - - phpenv rehash - - cd $plugin_dir - +- chmod +x bin/install-dependencies.sh +- ". ./bin/install-dependencies.sh" script: - grunt travis \ No newline at end of file +- if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then grunt travis; fi; +before_deploy: +- chmod +x bin/prepare-deploy.sh +- ". ./bin/prepare-deploy.sh" +deploy: +- provider: s3 + access_key_id: "$AWS_ACCESS_KEY" + secret_access_key: "$AWS_SECRET_KEY" + bucket: "$AWS_BUCKET" + skip_cleanup: true + acl: public_read + overwrite: true + local-dir: artifact/ + upload-dir: "$AWS_PRODUCTS_FOLDER/$THEMEISLE_REPO/latest" + on: + branch: "$MASTER_BRANCH" + repo: "$UPSTREAM_REPO" + condition: $TRAVIS_PHP_VERSION = "7.0" +- provider: s3 + access_key_id: "$AWS_ACCESS_KEY" + secret_access_key: "$AWS_SECRET_KEY" + bucket: "$AWS_BUCKET" + skip_cleanup: true + acl: public_read + overwrite: true + local-dir: artifact/ + upload-dir: "$AWS_PRODUCTS_FOLDER/$THEMEISLE_REPO/$THEMEISLE_VERSION" + on: + repo: "$UPSTREAM_REPO" + branch: "$MASTER_BRANCH" + condition: $TRAVIS_PHP_VERSION = "7.0" +- provider: releases + api_key: "$GITHUB_TOKEN" + file: artifact/$THEMEISLE_REPO.zip + skip_cleanup: true + on: + tags: false + repo: "$UPSTREAM_REPO" + branch: "$MASTER_BRANCH" + condition: $TRAVIS_PHP_VERSION = "7.0" +after_deploy: +- chmod +x bin/deploy.sh +- ". ./bin/deploy.sh" diff --git a/bin/deploy.sh b/bin/deploy.sh new file mode 100644 index 00000000..cbfb8dda --- /dev/null +++ b/bin/deploy.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# We run this just one time, for a first job from the buid and just at once after_deploy hook. +if ! [ $AFTER_DEPLOY_RUN ] && [ "$TRAVIS_PHP_VERSION" == "7.0" ]; then + + # Flag the run in order to not be trigged again on the next after_deploy. + export AFTER_DEPLOY_RUN=1; + echo " Started deploy script. "; + + # Setup git username and email. + + git config user.name "selul" + git config user.email ${GITHUB_EMAIL} + + # Send changelog changes to git. + git checkout $MASTER_BRANCH + git add -v . + + # We use [skip ci] in message to prevent this commit to trigger the build. + git commit -a -m "[AUTO][skip ci] Updating changelog for v"$THEMEISLE_VERSION + git push --quiet "https://${GITHUB_TOKEN}@github.com/$UPSTREAM_REPO.git" HEAD:$MASTER_BRANCH + + # Tag the new release. + git tag -a "v$THEMEISLE_VERSION" -m "[AUTO] Release of $THEMEISLE_VERSION "; + git push --quiet "https://${GITHUB_TOKEN}@github.com/$UPSTREAM_REPO.git" --tags ; + sleep 5; + + # Sends the api call for creating the release. + # We use this as the travis release provider does not offer any way + # to set the body of the release. + API_JSON='{"tag_name": "v'$THEMEISLE_VERSION'","target_commitish": "'$MASTER_BRANCH'","name": "v'$THEMEISLE_VERSION'","body": "'$CHANGES'","draft": false,"prerelease": false}'; + curl -s --data "$API_JSON" "https://api.github.com/repos/$UPSTREAM_REPO/releases?access_token="$GITHUB_TOKEN > /dev/null; + + # Send update to the store + STORE_JSON='{"version": "'$THEMEISLE_VERSION'","id": "'$THEMEISLE_ID'","body": "'$CHANGES'"}'; + curl -s -H "Content-Type: application/json" -H "x-themeisle-auth: $THEMEISLE_AUTH" --data "$STORE_JSON" "$STORE_URL/wp-json/ti-endpoint/v1/update_changelog_new/" > /dev/null + + # Send data to demo server. + grunt sftp + + # Upload to Wordpress SVN + if [ ! -z "$WP_ORG_PASSWORD" ]; then + + svn co -q "http://svn.wp-plugins.org/$THEMEISLE_REPO" svn + + # Copy new content to svn trunk. + rsync -r -p dist/* svn/trunk + + # Create new SVN tag. + mkdir -p svn/tags/$THEMEISLE_VERSION + rsync -r -p dist/* svn/tags/$THEMEISLE_VERSION + + # Add new files to SVN + svn stat svn | grep '^?' | awk '{print $2}' | xargs -I x svn add x@ + # Remove deleted files from SVN + svn stat svn | grep '^!' | awk '{print $2}' | xargs -I x svn rm --force x@ + + svn stat svn + + # Commit to SVN + svn ci --no-auth-cache --username $WPORG_USER --password $WPORG_PASS svn -m "Release v$THEMEISLE_VERSION" + + fi + +fi; diff --git a/bin/install-dependencies.sh b/bin/install-dependencies.sh new file mode 100644 index 00000000..3fad0bdc --- /dev/null +++ b/bin/install-dependencies.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# We run this on PR or on push to MASTER_BRANCH. +if [ "$TRAVIS_PULL_REQUEST" != "false" ] || ( [ "$TRAVIS_EVENT_TYPE" == "push" ] && [ "$TRAVIS_REPO_SLUG" == "$UPSTREAM_REPO" ] && [ "$TRAVIS_BRANCH" == "$MASTER_BRANCH" ] ) ; then + + . $HOME/.nvm/nvm.sh + nvm install stable + nvm use stable + + npm install + npm install grunt-cli -g + + phpenv local 5.6 + + composer selfupdate 1.0.0 --no-interaction + composer install --no-interaction + phpenv local --unset + +fi; +# We dont install PHPCS if is not a PR. +if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + + # Install PHPCS. + pear install pear/PHP_CodeSniffer + + # Install WPCS standards. + git clone -b master --depth 1 https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git $HOME/wordpress-coding-standards + phpenv rehash + phpcs --config-set installed_paths $HOME/wordpress-coding-standards + phpenv rehash + + # Install wordpress for testing. + bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION + export PATH="$HOME/.composer/vendor/bin:$PATH" + + # Use phpunit 5.7 as WP dont support 6. + if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then + composer global require "phpunit/phpunit=5.7.*" ; + fi; +fi; \ No newline at end of file diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh new file mode 100644 index 00000000..aa2e2396 --- /dev/null +++ b/bin/install-wp-tests.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash + + +if [ $# -lt 3 ]; then + echo "usage: $0 [db-host] [wp-version] [force download]" + exit 1 +fi + +DB_NAME=$1 +DB_USER=$2 +DB_PASS=$3 +DB_HOST=${4-localhost} +WP_VERSION=${5-latest} +FORCE=${6-false} + +WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} +WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} + +download() { + if [ `which curl` ]; then + curl -s "$1" > "$2"; + elif [ `which wget` ]; then + wget -nv -O "$2" "$1" + fi +} + +if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then + WP_TESTS_TAG="tags/$WP_VERSION" +else + # http serves a single offer, whereas https serves multiple. we only want one + download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json + grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json + LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') + if [[ -z "$LATEST_VERSION" ]]; then + echo "Latest WordPress version could not be found" + exit 1 + fi + WP_TESTS_TAG="tags/$LATEST_VERSION" +fi + +if [[ $WP_TESTS_TAG == *"beta"* ]] +then + WP_TESTS_TAG="trunk" +fi + +set -ex + +install_wp() { + if [ $FORCE == 'true' ]; then + rm -Rf $WP_CORE_DIR + fi + + if [ -d $WP_CORE_DIR ]; then + return; + fi + + mkdir -p $WP_CORE_DIR + + if [ $WP_VERSION == 'latest' ]; then + local ARCHIVE_NAME='latest' + else + local ARCHIVE_NAME="wordpress-$WP_VERSION" + fi + + download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz + tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR + + download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php +} + +install_test_suite() { + if [ $FORCE == 'true' ]; then + rm -Rf $WP_TESTS_DIR + fi + + # portable in-place argument for both GNU sed and Mac OSX sed + if [[ $(uname -s) == 'Darwin' ]]; then + local ioption='-i .bak' + else + local ioption='-i' + fi + + # set up testing suite if it doesn't yet exist + if [ ! -d $WP_TESTS_DIR ]; then + # set up testing suite + mkdir -p $WP_TESTS_DIR + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data + fi + + cd $WP_TESTS_DIR + + if [ ! -f wp-tests-config.php ]; then + download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php + sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php + fi + +} + +install_db() { + # parse DB_HOST for port or socket references + local PARTS=(${DB_HOST//\:/ }) + local DB_HOSTNAME=${PARTS[0]}; + local DB_SOCK_OR_PORT=${PARTS[1]}; + local EXTRA="" + + if ! [ -z $DB_HOSTNAME ] ; then + if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then + EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" + elif ! [ -z $DB_SOCK_OR_PORT ] ; then + EXTRA=" --socket=$DB_SOCK_OR_PORT" + elif ! [ -z $DB_HOSTNAME ] ; then + EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" + fi + fi + + # create database + mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA +} + +install_wp +install_test_suite +install_db \ No newline at end of file diff --git a/bin/prepare-deploy.sh b/bin/prepare-deploy.sh new file mode 100644 index 00000000..4e506359 --- /dev/null +++ b/bin/prepare-deploy.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +#We make sure we run this just at one before_deploy hook. +if ! [ $BEFORE_DEPLOY_RUN ] && [ "$TRAVIS_PHP_VERSION" == "7.0" ]; then + + echo " Preparing deploy. "; + + # Flag the run. + export BEFORE_DEPLOY_RUN=1; + + # Parse the name of the repo. + export THEMEISLE_REPO=$(node -pe "require('./package.json').name") + + # Parse the version of the product. + + export THEMEISLE_VERSION=$(node -pe "require('./package.json').version") + + # Parse product category. + export THEMEISLE_CATEGORY=$(node -pe "require('./package.json').category") + + export DEMO_THEMEISLE_PATH="/sites/demo.themeisle.com/wp-content/$THEMEISLE_CATEGORY/$THEMEISLE_REPO"; + + # Build changelog based on commit message description. + CHANGELOG="\n ### v$THEMEISLE_VERSION - "$(date +'%Y-%m-%d')" \n **Changes:** \n"; + + # Remove first line from the commit as is it used as commit title. + NORMALIZED_MESSAGE=$(sed "1d" <<< "$TRAVIS_COMMIT_MESSAGE"); + + # Save changes list in a sepparately variable as we use it in the release body. + export CHANGES=""; + while read -r line; do + if ! [ -z $line ]; then + line=$(echo "${line//[$'\r\n']}"); + export CHANGES=$CHANGES'- '$line'\n'; + fi; + done <<< "$NORMALIZED_MESSAGE" + + # Concat changes and changelog title and prepend to the changelog file. + + CHANGELOG="$CHANGELOG $CHANGES"; + echo -e "$CHANGELOG $(cat CHANGELOG.md)" > CHANGELOG.md + + # Run the prepare deployment action + + grunt deploy +fi; \ No newline at end of file diff --git a/classes/Visualizer/Module/Admin.php b/classes/Visualizer/Module/Admin.php index fa2443fc..591e25b4 100644 --- a/classes/Visualizer/Module/Admin.php +++ b/classes/Visualizer/Module/Admin.php @@ -1,5 +1,4 @@ _addAction( 'load-post.php', 'enqueueMediaScripts' ); $this->_addAction( 'load-post-new.php', 'enqueueMediaScripts' ); $this->_addAction( 'admin_footer', 'renderTempaltes' ); - $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts' ); + $this->_addAction( 'admin_enqueue_scripts', 'enqueueLibraryScripts', null, 9 ); $this->_addAction( 'admin_menu', 'registerAdminMenu' ); - $this->_addFilter( 'media_view_strings', 'setupMediaViewStrings' ); $this->_addFilter( 'plugin_action_links', 'getPluginActionLinks', 10, 2 ); $this->_addFilter( 'plugin_row_meta', 'getPluginMetaLinks', 10, 2 ); + $this->_addFilter( 'visualizer_logger_flag', 'get_logger_flag', 10, 1 ); + $this->_addAjaxAction( Visualizer_Plugin::ACTION_TRACK, 'visualizer_enable_track' ); } /** - * Returns associated array of chart types and localized names. - * - * @since 1.0.0 - * - * @static - * @access private - * @return array The associated array of chart types with localized names. + * Enable track ajax action. */ - public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false ) { - $types = array( - 'pie' => array( 'name' => esc_html__( 'Pie', 'visualizer' ), 'enabled' => true ), - 'line' => array( 'name' => esc_html__( 'Line', 'visualizer' ), 'enabled' => true ), - 'area' => array( 'name' => esc_html__( 'Area', 'visualizer' ), 'enabled' => true ), - 'geo' => array( 'name' => esc_html__( 'Geo', 'visualizer' ), 'enabled' => true ), - 'bar' => array( 'name' => esc_html__( 'Bar', 'visualizer' ), 'enabled' => true ), - 'column' => array( 'name' => esc_html__( 'Column', 'visualizer' ), 'enabled' => true ), - 'gauge' => array( 'name' => esc_html__( 'Gauge', 'visualizer' ), 'enabled' => true ), - 'scatter' => array( 'name' => esc_html__( 'Scatter', 'visualizer' ), 'enabled' => true ), - 'candlestick' => array( 'name' => esc_html__( 'Candlestick', 'visualizer' ), 'enabled' => true ), - // pro types - 'table' => array( 'name' => esc_html__( 'Table', 'visualizer' ), 'enabled' => false ), - 'timeline' => array( 'name' => esc_html__( 'Timeline', 'visualizer' ), 'enabled' => false ), - 'combo' => array( 'name' => esc_html__( 'Combo', 'visualizer' ), 'enabled' => false ), - ); - - $types = apply_filters( 'visualizer_pro_chart_types', $types ); - - if ( $enabledOnly ) { - $filtered = array(); - foreach ( $types as $type => $array ) { - if ( ! $array['enabled'] ) { continue; - } - $filtered[ $type ] = $array; - } - $types = $filtered; + public function visualizer_enable_track() { + check_admin_referer( Visualizer_Plugin::ACTION_TRACK, 'nonce' ); + $status = $_GET['status']; + if ( $status == 'yes' ) { + update_option( 'visualizer_logger_flag', 'yes' ); + } else { + update_option( 'visualizer_logger_flag', 'no' ); } + wp_send_json_success( array( 'status' => $status ) ); + } - if ( $get2Darray ) { - $doubleD = array(); - foreach ( $types as $type => $array ) { - $doubleD[ $type ] = $array['name']; - } - $types = $doubleD; - } + /** + * Either the tracking is active or not. + * + * @return bool The flag status. + */ + public function get_logger_flag() { + $flag = get_option( 'visualizer_logger_flag', 'no' ); - return $types; + return ( $flag === 'yes' ); } /** @@ -123,18 +99,16 @@ public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darra */ public function enqueueMediaScripts() { global $typenow; - if ( post_type_supports( $typenow, 'editor' ) ) { wp_enqueue_style( 'visualizer-media', VISUALIZER_ABSURL . 'css/media.css', array( 'media-views' ), Visualizer_Plugin::VERSION ); - - wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true ); - wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true ); - wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', array( 'visualizer-google-jsapi-old' ), Visualizer_Plugin::VERSION, true ); - wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-google-jsapi-new', '//www.gstatic.com/charts/loader.js', array( 'media-editor' ), null, true ); + wp_enqueue_script( 'visualizer-google-jsapi-old', '//www.google.com/jsapi', array( 'visualizer-google-jsapi-new' ), null, true ); + wp_enqueue_script( 'visualizer-media-model', VISUALIZER_ABSURL . 'js/media/model.js', array( 'visualizer-google-jsapi-old' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-media-collection', VISUALIZER_ABSURL . 'js/media/collection.js', array( 'visualizer-media-model' ), Visualizer_Plugin::VERSION, true ); wp_enqueue_script( 'visualizer-media-controller', VISUALIZER_ABSURL . 'js/media/controller.js', array( 'visualizer-media-collection' ), Visualizer_Plugin::VERSION, true ); - wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true ); - wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true ); - wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-media-view', VISUALIZER_ABSURL . 'js/media/view.js', array( 'visualizer-media-controller' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-media-toolbar', VISUALIZER_ABSURL . 'js/media/toolbar.js', array( 'visualizer-media-view' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-media', VISUALIZER_ABSURL . 'js/media.js', array( 'visualizer-media-toolbar' ), Visualizer_Plugin::VERSION, true ); } } @@ -144,33 +118,126 @@ public function enqueueMediaScripts() { * @since 1.0.0 * * @access public + * * @param array $strings The array of media view strings. + * * @return array The extended array of media view strings. */ public function setupMediaViewStrings( $strings ) { $strings['visualizer'] = array( - 'actions' => array( + 'actions' => array( 'get_charts' => Visualizer_Plugin::ACTION_GET_CHARTS, 'delete_chart' => Visualizer_Plugin::ACTION_DELETE_CHART, ), 'controller' => array( 'title' => esc_html__( 'Visualizations', 'visualizer' ), ), - 'routers' => array( + 'routers' => array( 'library' => esc_html__( 'From Library', 'visualizer' ), 'create' => esc_html__( 'Create New', 'visualizer' ), ), - 'library' => array( - 'filters' => self::_getChartTypesLocalized( true, true ), - 'types' => array_keys( self::_getChartTypesLocalized( true, true ) ), + 'library' => array( + 'filters' => self::_getChartTypesLocalized( true, true ), + 'types' => array_keys( self::_getChartTypesLocalized( true, true ) ), ), - 'nonce' => wp_create_nonce(), - 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ), + 'nonce' => wp_create_nonce(), + 'buildurl' => add_query_arg( 'action', Visualizer_Plugin::ACTION_CREATE_CHART, admin_url( 'admin-ajax.php' ) ), ); return $strings; } + /** + * Returns associated array of chart types and localized names. + * + * @since 1.0.0 + * + * @static + * @access private + * @return array The associated array of chart types with localized names. + */ + public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darray = false ) { + $types = array( + 'pie' => array( + 'name' => esc_html__( 'Pie', 'visualizer' ), + 'enabled' => true, + ), + 'line' => array( + 'name' => esc_html__( 'Line', 'visualizer' ), + 'enabled' => true, + ), + 'area' => array( + 'name' => esc_html__( 'Area', 'visualizer' ), + 'enabled' => true, + ), + 'geo' => array( + 'name' => esc_html__( 'Geo', 'visualizer' ), + 'enabled' => true, + ), + 'bar' => array( + 'name' => esc_html__( 'Bar', 'visualizer' ), + 'enabled' => true, + ), + 'column' => array( + 'name' => esc_html__( 'Column', 'visualizer' ), + 'enabled' => true, + ), + 'gauge' => array( + 'name' => esc_html__( 'Gauge', 'visualizer' ), + 'enabled' => true, + ), + 'scatter' => array( + 'name' => esc_html__( 'Scatter', 'visualizer' ), + 'enabled' => true, + ), + 'candlestick' => array( + 'name' => esc_html__( 'Candlestick', 'visualizer' ), + 'enabled' => true, + ), + // pro types + 'table' => array( + 'name' => esc_html__( 'Table', 'visualizer' ), + 'enabled' => false, + ), + 'timeline' => array( + 'name' => esc_html__( 'Timeline', 'visualizer' ), + 'enabled' => false, + ), + 'combo' => array( + 'name' => esc_html__( 'Combo', 'visualizer' ), + 'enabled' => false, + ), + ); + $types = apply_filters( 'visualizer_pro_chart_types', $types ); + if ( $enabledOnly ) { + $filtered = array(); + foreach ( $types as $type => $array ) { + if ( ! is_array( $array ) ) { + // support for old pro + $array = array( 'enabled' => true, 'name' => $array ); + } + if ( ! $array['enabled'] ) { + continue; + } + $filtered[ $type ] = $array; + } + $types = $filtered; + } + if ( $get2Darray ) { + $doubleD = array(); + foreach ( $types as $type => $array ) { + if ( ! is_array( $array ) ) { + // support for old pro + $array = array( 'enabled' => true, 'name' => $array ); + } + $doubleD[ $type ] = $array['name']; + } + $types = $doubleD; + } + + return $types; + } + /** * Renders templates to use in media popup. * @@ -181,11 +248,9 @@ public function setupMediaViewStrings( $strings ) { */ public function renderTempaltes() { global $pagenow; - if ( 'post.php' != $pagenow && 'post-new.php' != $pagenow ) { return; } - $render = new Visualizer_Render_Templates(); $render->render(); } @@ -199,19 +264,24 @@ public function renderTempaltes() { * @uses wp_enqueue_media() To enqueue media stuff. * * @access public + * * @param string $suffix The current page suffix. */ public function enqueueLibraryScripts( $suffix ) { if ( $suffix == $this->_libraryPage ) { wp_enqueue_style( 'visualizer-library', VISUALIZER_ABSURL . 'css/library.css', array(), Visualizer_Plugin::VERSION ); - $this->_addFilter( 'media_upload_tabs', 'setupVisualizerTab' ); - wp_enqueue_media(); - wp_enqueue_script( 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array( 'jquery', 'media-views' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-library', VISUALIZER_ABSURL . 'js/library.js', array( + 'jquery', + 'media-views', + ), Visualizer_Plugin::VERSION, true ); wp_enqueue_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true ); wp_enqueue_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true ); - wp_enqueue_script( 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array( 'google-jsapi-old', 'visualizer-library' ), Visualizer_Plugin::VERSION, true ); + wp_enqueue_script( 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array( + 'google-jsapi-old', + 'visualizer-library', + ), Visualizer_Plugin::VERSION, true ); } } @@ -221,11 +291,14 @@ public function enqueueLibraryScripts( $suffix ) { * @since 1.0.0 * * @access public + * * @param array $tabs The array of media upload tabs. + * * @return array Extended array of media upload tabs. */ public function setupVisualizerTab( $tabs ) { $tabs['visualizer'] = 'Visualizer'; + return $tabs; } @@ -237,8 +310,8 @@ public function setupVisualizerTab( $tabs ) { * @access public */ public function registerAdminMenu() { - $title = esc_html__( 'Visualizer Library', 'visualizer' ); - $callback = array( $this, 'renderLibraryPage' ); + $title = esc_html__( 'Visualizer Library', 'visualizer' ); + $callback = array( $this, 'renderLibraryPage' ); $this->_libraryPage = add_submenu_page( 'upload.php', $title, $title, 'edit_posts', Visualizer_Plugin::NAME, $callback ); } @@ -257,14 +330,12 @@ public function renderLibraryPage() { 'default' => 1, ), ) ); - // the initial query arguments to fetch charts $query_args = array( 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, 'posts_per_page' => 6, 'paged' => $page, ); - // add chart type filter to the query arguments $filter = filter_input( INPUT_GET, 'type' ); if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) { @@ -278,34 +349,30 @@ public function renderLibraryPage() { } else { $filter = 'all'; } - // Added by Ash/Upwork - $filterByMeta = filter_input( INPUT_GET, 'filter', FILTER_SANITIZE_STRING ); + $filterByMeta = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING ); if ( $filterByMeta ) { - $query = array( - 'key' => Visualizer_Plugin::CF_SETTINGS, - 'value' => $filterByMeta, - 'compare' => 'LIKE', + $query = array( + 'key' => Visualizer_Plugin::CF_SETTINGS, + 'value' => $filterByMeta, + 'compare' => 'LIKE', ); - $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array(); - $meta[] = $query; - $query_args['meta_query'] = $meta; + $meta = isset( $query_args['meta_query'] ) ? $query_args['meta_query'] : array(); + $meta[] = $query; + $query_args['meta_query'] = $meta; } // Added by Ash/Upwork // fetch charts $charts = array(); - $query = new WP_Query( $query_args ); + $query = new WP_Query( $query_args ); while ( $query->have_posts() ) { $chart = $query->next_post(); - // fetch and update settings $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true ); unset( $settings['height'], $settings['width'] ); - - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ); + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ); $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type ); - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type ); - + $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type ); // add chart to the array $charts[ 'visualizer-' . $chart->ID ] = array( 'id' => $chart->ID, @@ -315,24 +382,32 @@ public function renderLibraryPage() { 'data' => $data, ); } - // enqueue charts array $ajaxurl = admin_url( 'admin-ajax.php' ); wp_localize_script( 'visualizer-library', 'visualizer', array( 'charts' => $charts, 'urls' => array( 'base' => add_query_arg( 'vpage', false ), - 'create' => add_query_arg( array( 'action' => Visualizer_Plugin::ACTION_CREATE_CHART, 'library' => 'yes' ), $ajaxurl ), - 'edit' => add_query_arg( array( 'action' => Visualizer_Plugin::ACTION_EDIT_CHART, 'library' => 'yes' ), $ajaxurl ), + 'create' => add_query_arg( array( + 'action' => Visualizer_Plugin::ACTION_CREATE_CHART, + 'library' => 'yes', + ), $ajaxurl ), + 'edit' => add_query_arg( array( + 'action' => Visualizer_Plugin::ACTION_EDIT_CHART, + 'library' => 'yes', + ), $ajaxurl ), + 'logger' => add_query_arg( array( + 'action' => Visualizer_Plugin::ACTION_TRACK, + 'library' => 'yes', + 'nonce' => wp_create_nonce( Visualizer_Plugin::ACTION_TRACK ), + ), $ajaxurl ), ), ) ); - // render library page - $render = new Visualizer_Render_Library(); - - $render->charts = $charts; - $render->type = $filter; - $render->types = self::_getChartTypesLocalized(); + $render = new Visualizer_Render_Library(); + $render->charts = $charts; + $render->type = $filter; + $render->types = self::_getChartTypesLocalized(); $render->pagination = paginate_links( array( 'base' => add_query_arg( 'vpage', '%#%' ), 'format' => '', @@ -340,7 +415,6 @@ public function renderLibraryPage() { 'total' => $query->max_num_pages, 'type' => 'array', ) ); - $render->render(); } @@ -350,8 +424,10 @@ public function renderLibraryPage() { * @since 1.0.0 * * @access public + * * @param array $links The array of original action links. * @param string $file The plugin basename. + * * @return array Updated array of action links. */ public function getPluginActionLinks( $links, $file ) { @@ -375,8 +451,10 @@ public function getPluginActionLinks( $links, $file ) { * @since 1.0.0 * * @access public + * * @param array $plugin_meta The array of a plugin meta links. * @param string $plugin_file The plugin's basename. + * * @return array Updated array of plugin meta links. */ public function getPluginMetaLinks( $plugin_meta, $plugin_file ) { diff --git a/classes/Visualizer/Module/Chart.php b/classes/Visualizer/Module/Chart.php index 6d424cd4..b4dd4c0a 100644 --- a/classes/Visualizer/Module/Chart.php +++ b/classes/Visualizer/Module/Chart.php @@ -1,5 +1,4 @@ _addAjaxAction( Visualizer_Plugin::ACTION_GET_CHARTS, 'getCharts' ); $this->_addAjaxAction( Visualizer_Plugin::ACTION_DELETE_CHART, 'deleteChart' ); $this->_addAjaxAction( Visualizer_Plugin::ACTION_CREATE_CHART, 'renderChartPages' ); $this->_addAjaxAction( Visualizer_Plugin::ACTION_EDIT_CHART, 'renderChartPages' ); $this->_addAjaxAction( Visualizer_Plugin::ACTION_UPLOAD_DATA, 'uploadData' ); $this->_addAjaxAction( Visualizer_Plugin::ACTION_CLONE_CHART, 'cloneChart' ); - // Added by Ash/Upwork $this->_addAjaxAction( Visualizer_Plugin::ACTION_EXPORT_DATA, 'exportData' ); - if ( defined( 'Visualizer_Pro' ) ) { - global $Visualizer_Pro; - list($action, $name, $class) = $Visualizer_Pro->_getAjaxAction( $this ); - $this->_addAjaxAction( $action, $name, $class ); - } // Added by Ash/Upwork } - /** - * Sends json response. - * - * @since 1.0.0 - * - * @access private - * @param array $results The response array. - */ - public function _sendResponse( $results ) { - header( 'Content-type: application/json' ); - nocache_headers(); - - echo json_encode( $results ); - exit; - } - - /** - * Returns chart data required for rendering. - * - * @since 1.0.0 - * - * @access private - * @param WP_Post $chart The chart object. - * @return array The array of chart data. - */ - private function _getChartArray( WP_Post $chart = null ) { - if ( is_null( $chart ) ) { - $chart = $this->_chart; - } - - $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ); - $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type ); - $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type ); - - return array( - 'type' => $type, - 'series' => $series, - 'settings' => get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true ), - 'data' => $data, - ); - } - /** * Fetches charts from database. * @@ -129,8 +80,7 @@ public function getCharts() { ), ) ), ); - - $filter = filter_input( INPUT_GET, 'filter', FILTER_SANITIZE_STRING ); + $filter = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING ); if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) { $query_args['meta_query'] = array( array( @@ -140,26 +90,64 @@ public function getCharts() { ), ); } - - $query = new WP_Query( $query_args ); - + $query = new WP_Query( $query_args ); $charts = array(); while ( $query->have_posts() ) { - $chart = $query->next_post(); - - $chart_data = $this->_getChartArray( $chart ); + $chart = $query->next_post(); + $chart_data = $this->_getChartArray( $chart ); $chart_data['id'] = $chart->ID; - - $charts[] = $chart_data; + $charts[] = $chart_data; } - - $this->_sendResponse( array( + self::_sendResponse( array( 'success' => true, 'data' => $charts, 'total' => $query->max_num_pages, ) ); } + /** + * Returns chart data required for rendering. + * + * @since 1.0.0 + * + * @access private + * + * @param WP_Post $chart The chart object. + * + * @return array The array of chart data. + */ + private function _getChartArray( WP_Post $chart = null ) { + if ( is_null( $chart ) ) { + $chart = $this->_chart; + } + $type = get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ); + $series = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_SERIES, get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ), $chart->ID, $type ); + $data = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA, unserialize( $chart->post_content ), $chart->ID, $type ); + + return array( + 'type' => $type, + 'series' => $series, + 'settings' => get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true ), + 'data' => $data, + ); + } + + /** + * Sends json response. + * + * @since 1.0.0 + * + * @access private + * + * @param array $results The response array. + */ + public static function _sendResponse( $results ) { + header( 'Content-type: application/json' ); + nocache_headers(); + echo json_encode( $results ); + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit(); + } + /** * Deletes a chart from database. * @@ -169,28 +157,30 @@ public function getCharts() { * @access public */ public function deleteChart() { - $is_post = $_SERVER['REQUEST_METHOD'] == 'POST'; + $is_post = $_SERVER['REQUEST_METHOD'] == 'POST'; $input_method = $is_post ? INPUT_POST : INPUT_GET; - - $chart_id = $success = false; - $nonce = wp_verify_nonce( filter_input( $input_method, 'nonce' ) ); - $capable = current_user_can( 'delete_posts' ); + $chart_id = $success = false; + $nonce = wp_verify_nonce( filter_input( $input_method, 'nonce' ) ); + $capable = current_user_can( 'delete_posts' ); if ( $nonce && $capable ) { - $chart_id = filter_input( $input_method, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) ); + $chart_id = filter_input( $input_method, 'chart', FILTER_VALIDATE_INT, array( + 'options' => array( + 'min_range' => 1, + ), + ) ); if ( $chart_id ) { - $chart = get_post( $chart_id ); + $chart = get_post( $chart_id ); $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER; } } - if ( $success ) { wp_delete_post( $chart_id, true ); } - if ( $is_post ) { - $this->_sendResponse( array( 'success' => $success ) ); + self::_sendResponse( array( + 'success' => $success, + ) ); } - wp_redirect( wp_get_referer() ); exit; } @@ -204,16 +194,13 @@ public function deleteChart() { * @access public */ public function renderChartPages() { - define( 'IFRAME_REQUEST', 1 ); - + defined( 'IFRAME_REQUEST' ) || define( 'IFRAME_REQUEST', 1 ); // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id - $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT ); + $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : ''; if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) { $default_type = 'line'; - - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' ); + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' ); $source->fetch(); - $chart_id = wp_insert_post( array( 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, 'post_title' => 'Visualization', @@ -221,37 +208,40 @@ public function renderChartPages() { 'post_status' => 'auto-draft', 'post_content' => $source->getData(), ) ); - if ( $chart_id && ! is_wp_error( $chart_id ) ) { add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type ); add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 ); add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() ); add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() ); - add_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, array( 'focusTarget' => 'datum' ) ); + add_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, array( + 'focusTarget' => 'datum', + ) ); } - wp_redirect( add_query_arg( 'chart', (int) $chart_id ) ); - exit; + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit(); } - // enqueue and register scripts and styles wp_register_style( 'visualizer-frame', VISUALIZER_ABSURL . 'css/frame.css', array(), Visualizer_Plugin::VERSION ); - wp_register_script( 'visualizer-frame', VISUALIZER_ABSURL . 'js/frame.js', array( 'jquery' ), Visualizer_Plugin::VERSION, true ); wp_register_script( 'google-jsapi-new', '//www.gstatic.com/charts/loader.js', array(), null, true ); wp_register_script( 'google-jsapi-old', '//www.google.com/jsapi', array( 'google-jsapi-new' ), null, true ); - wp_register_script( 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array( 'google-jsapi-old', 'google-jsapi-new', 'visualizer-frame' ), Visualizer_Plugin::VERSION, true ); - wp_register_script( 'visualizer-preview', VISUALIZER_ABSURL . 'js/preview.js', array( 'wp-color-picker', 'visualizer-render' ), Visualizer_Plugin::VERSION, true ); - + wp_register_script( 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array( + 'google-jsapi-old', + 'google-jsapi-new', + 'visualizer-frame', + ), Visualizer_Plugin::VERSION, true ); + wp_register_script( 'visualizer-preview', VISUALIZER_ABSURL . 'js/preview.js', array( + 'wp-color-picker', + 'visualizer-render', + ), Visualizer_Plugin::VERSION, true ); // added by Ash/Upwork - if ( defined( 'Visualizer_Pro' ) ) { + if ( VISUALIZER_PRO ) { global $Visualizer_Pro; $Visualizer_Pro->_addScriptsAndStyles(); } - // dispatch pages - $this->_chart = $chart; - switch ( filter_input( INPUT_GET, 'tab' ) ) { + $this->_chart = get_post( $chart_id ); + switch ( isset( $_GET['tab'] ) ? $_GET['tab'] : '' ) { case 'settings': // changed by Ash/Upwork $this->_handleDataAndSettingsPage(); @@ -261,150 +251,56 @@ public function renderChartPages() { $this->_handleTypesPage(); break; } - - exit; - } - - /** - * Handles chart type selection page. - * - * @since 1.0.0 - * - * @access private - */ - private function _handleTypesPage() { - // process post request - if ( $_SERVER['REQUEST_METHOD'] == 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) { - $type = filter_input( INPUT_POST, 'type' ); - if ( in_array( $type, Visualizer_Plugin::getChartTypes() ) ) { - // save new chart type - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, $type ); - - // if the chart has default data, update it with appropriate default data for new type - if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) { - $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' ); - $source->fetch(); - - $this->_chart->post_content = $source->getData(); - wp_update_post( $this->_chart->to_array() ); - - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() ); - } - - // redirect to next tab - // changed by Ash/Upwork - wp_redirect( add_query_arg( 'tab', 'settings' ) ); - return; - } - } - - $render = new Visualizer_Render_Page_Types(); - $render->type = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ); - $render->types = Visualizer_Module_Admin::_getChartTypesLocalized(); - $render->chart = $this->_chart; - - wp_enqueue_style( 'visualizer-frame' ); - wp_enqueue_script( 'visualizer-frame' ); - - wp_iframe( array( $render, 'render' ) ); - } - - /** - * Handles chart data page. - * - * @since 1.0.0 - * - * @access private - */ - private function _handleDataPage() { - $data = $this->_getChartArray(); - - $render = new Visualizer_Render_Page_Data(); - $render->chart = $this->_chart; - $render->type = $data['type']; - - unset( $data['settings']['width'], $data['settings']['height'] ); - - wp_enqueue_style( 'visualizer-frame' ); - wp_enqueue_script( 'visualizer-render' ); - wp_localize_script( 'visualizer-render', 'visualizer', array( - 'l10n' => array( - 'remotecsv_prompt' => esc_html__( 'Please, enter the URL of CSV file:', 'visualizer' ), - 'invalid_source' => esc_html__( 'You have entered invalid URL. Please, insert proper URL.', 'visualizer' ), - ), - 'charts' => array( - 'canvas' => $data, - ), - ) ); - - // Added by Ash/Upwork - if ( defined( 'Visualizer_Pro' ) ) { - global $Visualizer_Pro; - $Visualizer_Pro->_enqueueScriptsAndStyles( $data ); - } - // Added by Ash/Upwork - $this->_addAction( 'admin_head', 'renderFlattrScript' ); - - wp_iframe( array( $render, 'render' ) ); + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit(); } /** * Handle data and settings page */ private function _handleDataAndSettingsPage() { - if ( $_SERVER['REQUEST_METHOD'] == 'POST' && wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ) ) ) { + if ( $_SERVER['REQUEST_METHOD'] == 'POST' && isset( $_GET['nonce'] ) && wp_verify_nonce( $_GET['nonce'] ) ) { if ( $this->_chart->post_status == 'auto-draft' ) { $this->_chart->post_status = 'publish'; wp_update_post( $this->_chart->to_array() ); } - update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST ); - - $render = new Visualizer_Render_Page_Send(); + $render = new Visualizer_Render_Page_Send(); $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID ); - wp_iframe( array( $render, 'render' ) ); + return; } - - $data = $this->_getChartArray(); - - $sidebar = ''; + $data = $this->_getChartArray(); + $sidebar = ''; $sidebar_class = 'Visualizer_Render_Sidebar_Type_' . ucfirst( $data['type'] ); if ( class_exists( $sidebar_class, true ) ) { - $sidebar = new $sidebar_class( $data['settings'] ); + $sidebar = new $sidebar_class( $data['settings'] ); $sidebar->__series = $data['series']; - $sidebar->__data = $data['data']; + $sidebar->__data = $data['data']; } else { - $sidebar = apply_filters( 'visualizer_pro_chart_type_sidebar', '', $data ); + $sidebar = apply_filters( 'visualizer_pro_chart_type_sidebar', '', $data ); if ( $sidebar != '' ) { $sidebar->__series = $data['series']; - $sidebar->__data = $data['data']; + $sidebar->__data = $data['data']; } } - unset( $data['settings']['width'], $data['settings']['height'] ); - wp_enqueue_style( 'visualizer-frame' ); wp_enqueue_style( 'wp-color-picker' ); wp_enqueue_style( 'visualizer-frame' ); - wp_enqueue_script( 'visualizer-preview' ); wp_enqueue_script( 'visualizer-render' ); wp_localize_script( 'visualizer-render', 'visualizer', array( 'l10n' => array( - 'remotecsv_prompt' => esc_html__( 'Please, enter the URL of CSV file:', 'visualizer' ), - 'invalid_source' => esc_html__( 'You have entered invalid URL. Please, insert proper URL.', 'visualizer' ), + 'invalid_source' => esc_html__( 'You have entered invalid URL. Please, insert proper URL.', 'visualizer' ), ), 'charts' => array( 'canvas' => $data, ), ) ); - - $render = new Visualizer_Render_Page_Data(); - $render->chart = $this->_chart; - $render->type = $data['type']; - + $render = new Visualizer_Render_Page_Data(); + $render->chart = $this->_chart; + $render->type = $data['type']; $render->sidebar = $sidebar; if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) { $render->button = filter_input( INPUT_GET, 'action' ) == Visualizer_Plugin::ACTION_EDIT_CHART @@ -413,17 +309,52 @@ private function _handleDataAndSettingsPage() { } else { $render->button = esc_attr__( 'Insert Chart', 'visualizer' ); } - - if ( defined( 'Visualizer_Pro' ) ) { + if ( VISUALIZER_PRO ) { global $Visualizer_Pro; $Visualizer_Pro->_enqueueScriptsAndStyles( $data ); } - $this->_addAction( 'admin_head', 'renderFlattrScript' ); + wp_iframe( array( $render, 'render' ) ); + } + /** + * Handles chart type selection page. + * + * @since 1.0.0 + * + * @access private + */ + private function _handleTypesPage() { + // process post request + if ( $_SERVER['REQUEST_METHOD'] == 'POST' && wp_verify_nonce( filter_input( INPUT_POST, 'nonce' ) ) ) { + $type = filter_input( INPUT_POST, 'type' ); + if ( in_array( $type, Visualizer_Plugin::getChartTypes() ) ) { + // save new chart type + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, $type ); + // if the chart has default data, update it with appropriate default data for new type + if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) { + $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' ); + $source->fetch(); + $this->_chart->post_content = $source->getData(); + wp_update_post( $this->_chart->to_array() ); + update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() ); + } + // redirect to next tab + // changed by Ash/Upwork + wp_redirect( add_query_arg( 'tab', 'settings' ) ); + + return; + } + } + $render = new Visualizer_Render_Page_Types(); + $render->type = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ); + $render->types = Visualizer_Module_Admin::_getChartTypesLocalized(); + $render->chart = $this->_chart; + wp_enqueue_style( 'visualizer-frame' ); + wp_enqueue_script( 'visualizer-frame' ); wp_iframe( array( $render, 'render' ) ); } - // changed by Ash/Upwork + /** * Renders flattr script in the iframe * @@ -435,7 +366,7 @@ private function _handleDataAndSettingsPage() { public function renderFlattrScript() { echo ''; } - + // changed by Ash/Upwork /** * Parses uploaded CSV file and saves new data for the chart. * @@ -445,52 +376,51 @@ public function renderFlattrScript() { */ public function uploadData() { // validate nonce - if ( ! wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ) ) ) { + // do not use filter_input as it does not work for phpunit test cases, use filter_var instead + if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'] ) ) { status_header( 403 ); exit; } - // check chart, if chart exists - $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT ); + $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT ) : ''; if ( ! $chart_id || ! ( $chart = get_post( $chart_id ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) { status_header( 400 ); exit; } - + if ( ! isset( $_POST['vz-import-time'] ) ) { + apply_filters( 'visualizer_pro_remove_schedule', $chart_id ); + } $source = null; $render = new Visualizer_Render_Page_Update(); - if ( filter_input( INPUT_POST, 'remote_data', FILTER_VALIDATE_URL ) ) { + if ( isset( $_POST['remote_data'] ) && filter_var( $_POST['remote_data'], FILTER_VALIDATE_URL ) ) { $source = new Visualizer_Source_Csv_Remote( $_POST['remote_data'] ); + if ( isset( $_POST['vz-import-time'] ) ) { + apply_filters( 'visualizer_pro_chart_schedule', $chart_id, $_POST['remote_data'], $_POST['vz-import-time'] ); + } } elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) { $source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] ); - // Added by Ash/Upwork - } elseif ( defined( 'Visualizer_Pro' ) && isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) { - global $Visualizer_Pro; - $source = $Visualizer_Pro->_handleChartData( $_POST['chart_data'] ); + } elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) { + $source = apply_filters( 'visualizer_pro_handle_chart_data', $_POST['chart_data'], '' ); // Added by Ash/Upwork } else { $render->message = esc_html__( 'CSV file with chart data was not uploaded. Please, try again.', 'visualizer' ); } - if ( $source ) { if ( $source->fetch() ) { $chart->post_content = $source->getData(); wp_update_post( $chart->to_array() ); - update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() ); update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() ); update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 ); - - $render->data = json_encode( $source->getRawData() ); + $render->data = json_encode( $source->getRawData() ); $render->series = json_encode( $source->getSeries() ); } else { $render->message = esc_html__( 'CSV file is broken or invalid. Please, try again.', 'visualizer' ); } } - $render->render(); - exit; + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit(); } /** @@ -502,16 +432,19 @@ public function uploadData() { */ public function cloneChart() { $chart_id = $success = false; - $nonce = wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), Visualizer_Plugin::ACTION_CLONE_CHART ); - $capable = current_user_can( 'edit_posts' ); + $nonce = wp_verify_nonce( filter_input( INPUT_GET, 'nonce' ), Visualizer_Plugin::ACTION_CLONE_CHART ); + $capable = current_user_can( 'edit_posts' ); if ( $nonce && $capable ) { - $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) ); + $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT, array( + 'options' => array( + 'min_range' => 1, + ), + ) ); if ( $chart_id ) { - $chart = get_post( $chart_id ); + $chart = get_post( $chart_id ); $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER; } } - $redirect = wp_get_referer(); if ( $success ) { $new_chart_id = wp_insert_post( array( @@ -521,21 +454,18 @@ public function cloneChart() { 'post_status' => $chart->post_status, 'post_content' => $chart->post_content, ) ); - if ( $new_chart_id && ! is_wp_error( $new_chart_id ) ) { add_post_meta( $new_chart_id, Visualizer_Plugin::CF_CHART_TYPE, get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true ) ); add_post_meta( $new_chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, get_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, true ) ); add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SOURCE, get_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, true ) ); add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SERIES, get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true ) ); add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SETTINGS, get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true ) ); - $redirect = add_query_arg( array( 'page' => 'visualizer', 'type' => filter_input( INPUT_GET, 'type' ), ), admin_url( 'upload.php' ) ); } } - wp_redirect( $redirect ); exit; } @@ -549,47 +479,48 @@ public function cloneChart() { */ public function exportData() { check_ajax_referer( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION, 'security' ); - $chart_id = $success = false; - $capable = current_user_can( 'edit_posts' ); + $capable = current_user_can( 'edit_posts' ); if ( $capable ) { - $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) ); + $chart_id = isset( $_GET['chart'] ) ? filter_var( $_GET['chart'], FILTER_VALIDATE_INT, array( + 'options' => array( + 'min_range' => 1, + ), + ) ) : ''; if ( $chart_id ) { - $chart = get_post( $chart_id ); + $chart = get_post( $chart_id ); $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER; } } - if ( $success ) { - $settings = get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true ); - $filename = $settings['title']; + $settings = get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true ); + $filename = isset( $settings['title'] ) ? $settings['title'] : ''; if ( empty( $filename ) ) { - $filename = 'export.csv'; + $filename = 'export.csv'; } else { - $filename .= '.csv'; + $filename .= '.csv'; } - $rows = array(); - $series = get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true ); - $data = unserialize( $chart->post_content ); + $rows = array(); + $series = get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true ); + $data = unserialize( $chart->post_content ); if ( ! empty( $series ) ) { - $row = array(); + $row = array(); foreach ( $series as $array ) { - $row[] = $array['label']; + $row[] = $array['label']; } - $rows[] = $row; - + $rows[] = $row; $row = array(); foreach ( $series as $array ) { - $row[] = $array['type']; + $row[] = $array['type']; } - $rows[] = $row; + $rows[] = $row; } - if ( ! empty( $data ) ) { foreach ( $data as $array ) { // ignore strings - if ( ! is_array( $array ) ) { continue; } - + if ( ! is_array( $array ) ) { + continue; + } // if this is an array of arrays... if ( is_array( $array[0] ) ) { foreach ( $array as $arr ) { @@ -601,26 +532,57 @@ public function exportData() { } } } - - $fp = tmpfile(); + $fp = tmpfile(); foreach ( $rows as $row ) { fputcsv( $fp, $row ); } rewind( $fp ); - - $csv = ''; - while ( ($array = fgetcsv( $fp )) !== false ) { - if ( strlen( $csv ) > 0 ) { $csv .= PHP_EOL; } - $csv .= implode( ',', $array ); + $csv = ''; + while ( ( $array = fgetcsv( $fp ) ) !== false ) { + if ( strlen( $csv ) > 0 ) { + $csv .= PHP_EOL; + } + $csv .= implode( ',', $array ); } fclose( $fp ); - - echo wp_send_json_success(array( - 'csv' => $csv, - 'name' => $filename, - )); + echo wp_send_json_success( array( + 'csv' => $csv, + 'name' => $filename, + ) ); }// End if(). + defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit(); + } - exit; + /** + * Handles chart data page. + * + * @since 1.0.0 + * + * @access private + */ + private function _handleDataPage() { + $data = $this->_getChartArray(); + $render = new Visualizer_Render_Page_Data(); + $render->chart = $this->_chart; + $render->type = $data['type']; + unset( $data['settings']['width'], $data['settings']['height'] ); + wp_enqueue_style( 'visualizer-frame' ); + wp_enqueue_script( 'visualizer-render' ); + wp_localize_script( 'visualizer-render', 'visualizer', array( + 'l10n' => array( + 'invalid_source' => esc_html__( 'You have entered invalid URL. Please, insert proper URL.', 'visualizer' ), + ), + 'charts' => array( + 'canvas' => $data, + ), + ) ); + // Added by Ash/Upwork + if ( VISUALIZER_PRO ) { + global $Visualizer_Pro; + $Visualizer_Pro->_enqueueScriptsAndStyles( $data ); + } + // Added by Ash/Upwork + $this->_addAction( 'admin_head', 'renderFlattrScript' ); + wp_iframe( array( $render, 'render' ) ); } } diff --git a/classes/Visualizer/Module/Frontend.php b/classes/Visualizer/Module/Frontend.php index 02aa62ab..c8fba789 100644 --- a/classes/Visualizer/Module/Frontend.php +++ b/classes/Visualizer/Module/Frontend.php @@ -151,7 +151,9 @@ public function renderChart( $atts ) { // enqueue visualizer render and update render localizations wp_enqueue_script( 'visualizer-render' ); - wp_localize_script( 'visualizer-render', 'visualizer', array( 'charts' => $this->_charts ) ); + wp_localize_script( 'visualizer-render', 'visualizer', array( + 'charts' => $this->_charts, + ) ); // return placeholder div return '
'; diff --git a/classes/Visualizer/Module/Sources.php b/classes/Visualizer/Module/Sources.php index e07f4d09..66506377 100644 --- a/classes/Visualizer/Module/Sources.php +++ b/classes/Visualizer/Module/Sources.php @@ -1,5 +1,4 @@ _addFilter( Visualizer_Plugin::FILTER_GET_CHART_SERIES, 'filterChartSeries', 1, 2 ); $this->_addFilter( Visualizer_Plugin::FILTER_GET_CHART_DATA, 'filterChartData', 1, 2 ); + $this->_addFilter( 'visualizer_pro_upsell', 'addProUpsell', 10, 2 ); + } + + /** + * Filters chart sereis. + * + * @since 1.1.0 + * + * @access public + * + * @param array $series The array of chart series. + * @param int $chart_id The chart id. + * + * @return array The array of filtered series. + */ + public function filterChartSeries( $series, $chart_id ) { + $source = $this->_getSource( $chart_id ); + if ( ! $source ) { + return $series; + } + + return $source->repopulateSeries( $series, $chart_id ); } /** @@ -62,7 +83,9 @@ public function __construct( Visualizer_Plugin $plugin ) { * @since 1.1.0 * * @access private + * * @param int $chart_id The chart id. + * * @return Visualizer_Source The source object if source exists, otherwise FALSE. */ private function _getSource( $chart_id ) { @@ -71,7 +94,6 @@ private function _getSource( $chart_id ) { if ( ! class_exists( $class, true ) ) { return false; } - $this->_sources[ $chart_id ] = new $class(); } @@ -79,41 +101,57 @@ private function _getSource( $chart_id ) { } /** - * Filters chart sereis. + * Filters chart data. * * @since 1.1.0 * * @access public - * @param array $series The array of chart series. + * + * @param array $data The array of chart data. * @param int $chart_id The chart id. - * @return array The array of filtered series. + * + * @return array The array of filtered data. */ - public function filterChartSeries( $series, $chart_id ) { + public function filterChartData( $data, $chart_id ) { $source = $this->_getSource( $chart_id ); if ( ! $source ) { - return $series; + return $data; } - return $source->repopulateSeries( $series, $chart_id ); + return $source->repopulateData( $data, $chart_id ); } /** - * Filters chart data. + * Add the pro upsell html. * - * @since 1.1.0 + * @param string $old The previous html string. + * @param string $feature What feature is this filter running for. * - * @access public - * @param array $data The array of chart data. - * @param int $chart_id The chart id. - * @return array The array of filtered data. + * @return string The new html code. */ - public function filterChartData( $data, $chart_id ) { - $source = $this->_getSource( $chart_id ); - if ( ! $source ) { - return $data; + public function addProUpsell( $old, $feature = null ) { + $return = ''; + $feature = strval( $feature ); + if ( empty( $feature ) || ( $feature == 'schedule-chart' && ! apply_filters( 'visualizer_is_business', false ) ) ) { + $plan = 'PRO'; + if ( $feature === 'schedule-chart' ) { + $plan = 'BUSINESS'; + } + $return = '
'; + $return .= '
'; + $return .= '
'; + $return .= '

' . sprintf( __( 'Enable this feature in %s version!', 'visualizer' ), $plan ) . '

'; + $return .= ' ' . __( 'Buy now', 'visualizer' ) . ''; + $return .= '
'; + $return .= '
'; + $return .= '
'; + } + if ( empty( $feature ) && defined( 'VISUALIZER_PRO_VERSION' ) ) { + remove_filter( 'visualizer_pro_upsell', 'addProUpsell', 10, 1 ); + $return = ''; } - return $source->repopulateData( $data, $chart_id ); + return $return; } } diff --git a/classes/Visualizer/Plugin.php b/classes/Visualizer/Plugin.php index cc9fc7fb..a0c79990 100644 --- a/classes/Visualizer/Plugin.php +++ b/classes/Visualizer/Plugin.php @@ -1,5 +1,4 @@ Visualizer_Plugin::ACTION_DELETE_CHART, - 'nonce' => wp_create_nonce(), - 'chart' => $chart_id, - ), $ajax_url ); - - $clone_url = add_query_arg( array( - 'action' => Visualizer_Plugin::ACTION_CLONE_CHART, - 'nonce' => wp_create_nonce( Visualizer_Plugin::ACTION_CLONE_CHART ), - 'chart' => $chart_id, - 'type' => $this->type, - ), $ajax_url ); - - $export_link = add_query_arg( array( - 'action' => Visualizer_Plugin::ACTION_EXPORT_DATA, - 'chart' => $chart_id, - 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), - ), admin_url( 'admin-ajax.php' ) ); - - echo '
'; - echo '
'; - echo ''; - echo '
'; - echo ''; + } } /** @@ -86,27 +73,29 @@ private function _renderChartBox( $placeholder_id, $chart_id ) { */ private function _renderLibrary() { // Added by Ash/Upwork - $filterBy = null; - if ( isset( $_GET['filter'] ) && strlen( $_GET['filter'] ) > 0 ) { - $filterBy = filter_input( INPUT_GET, 'filter', FILTER_SANITIZE_STRING ); + $filterBy = null; + if ( isset( $_GET['s'] ) && strlen( $_GET['s'] ) > 0 ) { + $filterBy = filter_input( INPUT_GET, 's', FILTER_SANITIZE_STRING ); } - echo ''; // Added by Ash/Upwork echo '
'; - echo ''; + echo '
'; echo '
'; - + echo '
'; if ( ! empty( $this->charts ) ) { echo '
'; - foreach ( $this->charts as $placeholder_id => $chart ) { + foreach ( $this->charts as $placeholder_id => $chart ) { $this->_renderChartBox( $placeholder_id, $chart['id'] ); } echo '
'; - if ( is_array( $this->pagination ) ) { - echo '
    '; + echo '
      '; foreach ( $this->pagination as $page ) { - echo '
    • ', $page, '
    • '; + echo '
    • ', $page, '
    • '; } echo '
    '; } } else { echo '
    '; - echo '
    '; - echo '
    '; - echo '
    ', esc_html__( 'No charts found', 'visualizer' ), '
    '; - echo '
    '; - echo ''; - echo '
    '; + echo '
    '; + echo '
    '; + echo '
    ', esc_html__( 'No charts found', 'visualizer' ), '
    '; + echo '
    '; + echo ''; + echo '
    '; echo '
    '; } + $this->_renderSidebar(); + echo '
'; } /** - * Renders library page. + * Renders chart's box block. * * @since 1.0.0 * - * @access protected + * @access private + * + * @param string $placeholder_id The placeholder's id for the chart. + * @param int $chart_id The id of the chart. */ - protected function _toHTML() { - echo '
'; - echo '

'; - echo '

'; - esc_html_e( 'Visualizer Library', 'visualizer' ); - echo ' ', esc_html__( 'Add New', 'visualizer' ), ''; - echo '

'; - - $this->_renderMessages(); - $this->_renderLibrary(); + private function _renderChartBox( $placeholder_id, $chart_id ) { + $ajax_url = admin_url( 'admin-ajax.php' ); + $delete_url = add_query_arg( array( + 'action' => Visualizer_Plugin::ACTION_DELETE_CHART, + 'nonce' => wp_create_nonce(), + 'chart' => $chart_id, + ), $ajax_url ); + $clone_url = add_query_arg( array( + 'action' => Visualizer_Plugin::ACTION_CLONE_CHART, + 'nonce' => wp_create_nonce( Visualizer_Plugin::ACTION_CLONE_CHART ), + 'chart' => $chart_id, + 'type' => $this->type, + ), $ajax_url ); + $export_link = add_query_arg( array( + 'action' => Visualizer_Plugin::ACTION_EXPORT_DATA, + 'chart' => $chart_id, + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), + ), admin_url( 'admin-ajax.php' ) ); + echo '
'; + echo '
'; + echo ''; + echo '
'; + echo ''; echo '
'; } /** - * Renders notification messages if need be. - * - * @since 1.4.2 - * - * @access private + * Render sidebar. */ - private function _renderMessages() { - if ( ! filter_var( ini_get( 'allow_url_fopen' ), FILTER_VALIDATE_BOOLEAN ) ) { - echo '
'; - echo '

'; - printf( esc_html__( '%s option is disabled in your php.ini config. Please, enable it by change its value to 1. This option increases the speed of remote CSV uploading.', 'visualizer' ), 'allow_url_fopen' ); - echo '

'; + private function _renderSidebar() { + if ( ! VISUALIZER_PRO ) { + $checked = apply_filters( 'visualizer_logger_flag', false ); + $checked = ( $checked === false ) ? '' : 'checked'; + echo '
'; + echo '
'; + echo '

' . __( 'Gain more editing power', 'visualizer' ) . '

    '; + echo '
  • ' . __( 'Spreadsheet like editor', 'visualizer' ) . '
  • '; + echo '
  • ' . __( 'Import from other charts', 'visualizer' ) . '
  • '; + echo '
  • ' . __( 'Auto-sync with online files', 'visualizer' ) . '
  • '; + echo '
  • ' . __( '3 more chart types', 'visualizer' ) . '
'; + echo '' . __( 'View more features', 'visualizer' ) . ''; + echo '
'; + echo '
'; + echo ''; + echo '' . __( 'Enable Tracking', 'visualizer' ) . '*'; + echo '

*' . __( 'Allow Visualizer to anonymously track how this plugin is used and help us make the plugin better. No sensitive data is tracked.', 'visualizer' ) . '

'; + echo '
'; echo '
'; } } diff --git a/classes/Visualizer/Render/Page.php b/classes/Visualizer/Render/Page.php index 8fd85671..aa5eacd6 100644 --- a/classes/Visualizer/Render/Page.php +++ b/classes/Visualizer/Render/Page.php @@ -64,17 +64,8 @@ protected function _renderContent() {} */ protected function _renderSidebar() { echo ''; } diff --git a/classes/Visualizer/Render/Page/Data.php b/classes/Visualizer/Render/Page/Data.php index e3f7a24a..f144f28b 100644 --- a/classes/Visualizer/Render/Page/Data.php +++ b/classes/Visualizer/Render/Page/Data.php @@ -39,13 +39,13 @@ class Visualizer_Render_Page_Data extends Visualizer_Render_Page { */ protected function _renderContent() { // Added by Ash/Upwork - if ( defined( 'Visualizer_Pro' ) ) { + if ( VISUALIZER_PRO ) { global $Visualizer_Pro; $Visualizer_Pro->_addEditor(); } // Added by Ash/Upwork echo '
'; - echo ''; + echo ''; echo '
'; } @@ -63,63 +63,176 @@ protected function _renderSidebarContent() { 'chart' => $this->chart->ID, ), admin_url( 'admin-ajax.php' ) ); - echo ''; - echo '
'; - echo ''; - echo '

'; - esc_html_e( 'Select and upload your data CSV file here. The first row of the CSV file should contain the column headings. The second one should contain series type (string, number, boolean, date, datetime, timeofday).', 'visualizer' ); - echo '

'; - - echo '

'; - esc_html_e( 'If you are unsure about how to format your data CSV then please take a look at this sample:', 'visualizer' ); - echo ' ', $this->type, '.csv '; - printf( esc_html__( 'or read how you can add Google spreadsheet in following %1$sarticle%1$s.', 'visualizer' ), '', '' ); - echo '

'; - - echo '
'; - echo '
'; - echo ''; - echo '
'; - echo '
'; - echo ''; - esc_attr_e( 'From Computer', 'visualizer' ); - echo '
'; - - echo '', esc_html__( 'From Web', 'visualizer' ), ''; - // Added by Ash/Upwork - if ( defined( 'Visualizer_Pro' ) ) { - global $Visualizer_Pro; - $Visualizer_Pro->_addFormElements(); - } else { - // Added by Ash/Upwork - echo '
'; - } - echo '
'; - echo '
'; + ?> + +
    +
  • +
    +

    +
    +
      +
        +
      • +

        +
        +

        +

        type . '.csv" target="_blank">' , $this->type , '.csv' ); ?>

        +
        + +
        + +
        + +
        +
        +
      • +
      • +

        +
          +
        • + - // added by Ash/Upwork - if ( defined( 'Visualizer_Pro' ) ) { - global $Visualizer_Pro; - $Visualizer_Pro->_addEditorElements(); - } else { -?> - - - - +

          +

          type . '.csv" target="_blank">' , $this->type , '.csv' ); ?>

          +

          this tutorial', 'visualizer' ); ?>

          +
          +
          + - echo''; - // Added by Ash/Upwork - echo '
          '; - echo '
'; +
+ + +
+ +
  • + +
    +

    +

    this tutorial', 'visualizer' ); ?>

    +

    +
    +
    + +

    + +
    + - // changed by Ash/Upwork - echo '
    '; - echo ''; - echo $this->sidebar; - echo ''; - echo '
    '; + + + +
    +
  • + + +
  • +

    +
    +
    +

    +
    + +
    + + +
    +
    +
  • +
  • +

    +
    + +
    + +
    +
    +

    + + + +
    +
    +
  • + + + +
  • +

    +
    + +

    +
    +
      +
      + sidebar; ?> +
      +
    +
  • +
  • + +
  • + + + '; echo ''; - esc_html_e( 'Back', 'visualizer' ); + esc_html_e( 'Back', 'visualizer' ); echo ''; echo '
    '; echo ''; diff --git a/classes/Visualizer/Render/Page/Types.php b/classes/Visualizer/Render/Page/Types.php index b9ce32fe..ebc8db8a 100644 --- a/classes/Visualizer/Render/Page/Types.php +++ b/classes/Visualizer/Render/Page/Types.php @@ -90,7 +90,7 @@ protected function _renderSidebar() {} * @access protected */ protected function _renderToolbar() { - if ( defined( 'Visualizer_Pro' ) ) { + if ( VISUALIZER_PRO ) { global $Visualizer_Pro; } echo ''; diff --git a/classes/Visualizer/Render/Page/Update.php b/classes/Visualizer/Render/Page/Update.php index 9d170a94..5ff5d6d8 100644 --- a/classes/Visualizer/Render/Page/Update.php +++ b/classes/Visualizer/Render/Page/Update.php @@ -52,11 +52,10 @@ protected function _toHTML() { echo '}'; // added by Ash/Upwork - if ( defined( 'Visualizer_Pro' ) ) { + if ( VISUALIZER_PRO ) { global $Visualizer_Pro; $Visualizer_Pro->_addUpdateHook( $this->series, $this->data ); } - // Added by Ash/Upwork } else { echo 'alert("', $this->message, '");'; } diff --git a/classes/Visualizer/Render/Sidebar.php b/classes/Visualizer/Render/Sidebar.php index 344f5f5e..15c0c5af 100644 --- a/classes/Visualizer/Render/Sidebar.php +++ b/classes/Visualizer/Render/Sidebar.php @@ -476,9 +476,12 @@ protected static function _renderGroupEnd() { * @param boolean $open Determines whether the section items block has to be expanded or collapsed. */ protected static function _renderSectionStart( $title = false, $open = true ) { - echo '
  • '; + if ( ! empty( $title ) ) { + echo '
  • '; echo '', $title, ''; + } else { + echo '
  • '; } echo '
    '; } diff --git a/classes/Visualizer/Source.php b/classes/Visualizer/Source.php index 7adde3bd..0a527a47 100644 --- a/classes/Visualizer/Source.php +++ b/classes/Visualizer/Source.php @@ -1,5 +1,4 @@ _data; } + /** + * Re populates series if the source is dynamic. + * + * @since 1.1.0 + * + * @access public + * + * @param array $series The actual array of series. + * @param int $chart_id The chart id. + * + * @return array The re populated array of series or old one. + */ + public function repopulateSeries( $series, $chart_id ) { + return $series; + } + + /** + * Re populates data if the source is dynamic. + * + * @since 1.1.0 + * + * @access public + * + * @param array $data The actual array of data. + * @param int $chart_id The chart id. + * + * @return array The re populated array of data or old one. + */ + public function repopulateData( $data, $chart_id ) { + return $data; + } + /** * Normalizes values according to series' type. * * @since 1.0.0 * * @access protected + * * @param array $data The row of data. + * * @return array Normalized row of data. */ protected function _normalizeData( $data ) { @@ -124,14 +200,12 @@ protected function _normalizeData( $data ) { if ( ! isset( $data[ $i ] ) ) { $data[ $i ] = null; } - if ( is_null( $data[ $i ] ) ) { continue; } - switch ( $series['type'] ) { case 'number': - $data[ $i ] = ( is_numeric( $data[ $i ] ) ) ? floatval( $data[ $i ] ) : (is_numeric( str_replace( ',', '', $data[ $i ] ) ) ? floatval( str_replace( ',', '', $data[ $i ] ) ) : null); + $data[ $i ] = ( is_numeric( $data[ $i ] ) ) ? floatval( $data[ $i ] ) : ( is_numeric( str_replace( ',', '', $data[ $i ] ) ) ? floatval( str_replace( ',', '', $data[ $i ] ) ) : null ); break; case 'boolean': $data[ $i ] = ! empty( $data[ $i ] ) ? filter_validate( $data[ $i ], FILTER_VALIDATE_BOOLEAN ) : null; @@ -149,56 +223,8 @@ protected function _normalizeData( $data ) { break; } } - // error_log(print_r($data,true)); - return $data; - } - /** - * Validates series tyeps. - * - * @since 1.0.1 - * - * @static - * @access protected - * @param array $types The icoming series types. - * @return boolean TRUE if sereis types are valid, otherwise FALSE. - */ - protected static function _validateTypes( $types ) { - $allowed_types = array( 'string', 'number', 'boolean', 'date', 'datetime', 'timeofday' ); - foreach ( $types as $type ) { - if ( ! in_array( $type, $allowed_types ) ) { - return false; - } - } - - return true; - } - - /** - * Re populates series if the source is dynamic. - * - * @since 1.1.0 - * - * @access public - * @param array $series The actual array of series. - * @param int $chart_id The chart id. - * @return array The re populated array of series or old one. - */ - public function repopulateSeries( $series, $chart_id ) { - return $series; - } - - /** - * Re populates data if the source is dynamic. - * - * @since 1.1.0 - * - * @access public - * @param array $data The actual array of data. - * @param int $chart_id The chart id. - * @return array The re populated array of data or old one. - */ - public function repopulateData( $data, $chart_id ) { + // error_log(print_r($data,true)); return $data; } diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..8f2955bf --- /dev/null +++ b/composer.json @@ -0,0 +1,46 @@ +{ + "name": "codeinwp/visualizer", + "description": "Visualizer for WordPress.", + "keywords": [ + "wordpress", + "charts", + "visualization" + ], + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/Codeinwp/themeisle-sdk" + } + ], + "homepage": "https://themeisle.com/plugins/visualizer/", + "license": "GPL-2.0+", + "authors": [ + { + "name": "ThemeIsle Team", + "email": "friends@themeisle.com.com", + "homepage": "https://themeisle.com" + } + ], + "type": "wordpress-plugin", + "support": { + "issues": "https://github.com/Codeinwp/visualizer/issues", + "source": "https://github.com/Codeinwp/visualizer" + }, + "require": { + "codeinwp/themeisle-sdk": "master", + "xrstf/composer-php52": "^1.0.20" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "scripts": { + "post-install-cmd": [ + "xrstf\\Composer52\\Generator::onPostInstallCmd" + ], + "post-update-cmd": [ + "xrstf\\Composer52\\Generator::onPostInstallCmd" + ], + "post-autoload-dump": [ + "xrstf\\Composer52\\Generator::onPostInstallCmd" + ] + } +} \ No newline at end of file diff --git a/css/frame.css b/css/frame.css index 25f298a4..840fd991 100644 --- a/css/frame.css +++ b/css/frame.css @@ -43,13 +43,6 @@ -webkit-overflow-scrolling: touch; } -.group-wrapper { - margin: 0; - padding: 0; - border-top: 1px solid #dfdfdf; - list-style: none; -} - .group { margin: 0; font-size: 12px; @@ -57,104 +50,150 @@ list-style: none; } -.group.open { - border-bottom: 1px solid #dfdfdf; +.group .group-header .group-title { + margin: 10px 0; + padding: 15px 20px; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + color: #555d66; + background: #fff; } -.group-title { +.group-wrapper ul .group-title { + border-top: 1px solid #ddd; +} + +.group-wrapper ul li { + border-top: 1px solid #ddd; +} + +.group-wrapper ul ul li.subsection { + margin: 5px; + border: 1px solid #ddd; +} + +.group-wrapper .group .group .group-title { position: relative; margin: 0; - padding: 10px 20px; - border-top: 1px solid white; - border-bottom: 1px solid #dfdfdf; - background: whiteSmoke; - background-image: -webkit-gradient(linear, left bottom, left top, from(#eee), to(whiteSmoke)); - background-image: -webkit-linear-gradient(bottom, #eee, whiteSmoke); - background-image: -webkit-gradient( linear, left top, left bottom, from(#eee), to(whiteSmoke)); - background-image: -webkit-linear-gradient( top, #eee, whiteSmoke); - background-image: linear-gradient( to bottom, #eee, whiteSmoke); - text-shadow: 0 1px 0 white; - font-family: Georgia, "Times New Roman", "Bitstream Charter", Times, serif; - font-family: "Open Sans",sans-serif; - font-size: 15px; - font-weight: normal; - font-weight: 700; + padding: 10px 10px 11px 14px; + border-top: none; + border-bottom: none; + border-left: 4px solid #fff; + color: #555d66; + background-color: #fff; + font-size: 14px; + font-weight: 600; + line-height: 21px; cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.group-title:hover, -.group.open .group-title { - color: white; - background: gray; - background-image: -webkit-gradient(linear, left bottom, left top, from(#6d6d6d), to(gray)); - background-image: -webkit-linear-gradient(bottom, #6d6d6d, gray); - background-image: -webkit-gradient( linear, left top, left bottom, from(#6d6d6d), to(gray)); - background-image: -webkit-linear-gradient( top, #6d6d6d, gray); - background-image: linear-gradient( to bottom, #6d6d6d, gray); - text-shadow: 0 -1px 0 #333; - font-family: "Open Sans", sans-serif; - font-weight: 700; + -webkit-transition: 0.15s color ease-in-out,0.15s background-color ease-in-out,0.15s border-color ease-in-out; + transition: 0.15s color ease-in-out,0.15s background-color ease-in-out,0.15s border-color ease-in-out; } -.group-title::after { +.group-wrapper .group .group:hover .group-title, +.group-wrapper .group .group.open .group-title { + border-left-color: #0073aa; + color: #0073aa; + background: #f3f3f5; +} + +.group-wrapper .group .group .group-title:after { position: absolute; z-index: 1; - top: 15px; - right: 20px; - width: 0; - height: 0; - border-width: 6px 6px 0; - border-style: solid; - border-color: #ccc transparent; - content: ""; + top: 11px; + right: 10px; + color: #a0a5aa; + font: 400 20px/1 dashicons; + content: "\f345"; } -.group-title:hover::after, -.group.open .group-title::after { - border-color: #eee transparent; +.group-wrapper .group .group.open .group-title:after { + content: "\f347"; +} + +.group-wrapper .group .customize-section-back { + display: block; + float: left; + width: 42px; + height: 49px; + margin: 0 15px 0 0; + padding: 0; + border: none; + border-top: 1px solid #ddd; + border-right: 1px solid #ddd; + border-left: 4px solid #fff; + background: #fff; + -webkit-box-shadow: none; + box-shadow: none; + cursor: pointer; + -webkit-transition: color 0.15s ease-in-out,border-color 0.15s ease-in-out,background 0.15s ease-in-out; + transition: color 0.15s ease-in-out,border-color 0.15s ease-in-out,background 0.15s ease-in-out; +} + +.group-wrapper .group .customize-section-back:hover { + border-left-color: #0073aa; + outline: 0; + color: #0073aa; + background: #f3f3f5; +} + +.group-wrapper .group .customize-section-back:before { + position: relative; + top: -11px; + left: -2px; + font: 400 20px/72px dashicons; + content: "\f341"; +} + +.group-wrapper.full-height { + float: left; + position: relative; + width: 100%; + height: 100%; + margin: 0; } -.group:hover .group-title { - border-top-color: gray; +.group.bottom-fixed { + display: block; + position: absolute; + bottom: 0; + width: 100%; } -.group.open .group-title { - border-top-color: #6d6d6d; +.group ul li h2, +.group ul li h3 { + padding: 7px 15px 7px 35px; } -.group.open .group-title::after { - border-width: 0 6px 6px; +.group h2 .dashicons { + margin-right: 5px; + vertical-align: -5px; } .group-content { display: none; - overflow: hidden; margin: 0; - padding: 10px 0 20px 0; + padding: 0; background-color: #fdfdfd; } div.group-content { - padding: 10px 20px 20px; + padding: 15px; } -.group.open .group-content { +.group.open > .group-content { display: block; } .group-description { margin: 0; - padding: 5px 20px 10px; + padding: 5px; color: #555; font-size: 12px; + text-align: left; } div.group-content .group-description { - padding: 0; + padding: 5px; font-family: "Montserrat",sans-serif; font-weight: 300; } @@ -180,6 +219,13 @@ div.group-content .group-description { cursor: pointer; } +.group-wrapper ul ul li .section-title { + margin-bottom: 0; + border: none; + -webkit-box-shadow: none; + box-shadow: none; +} + .section-title::after { position: absolute; z-index: 1; @@ -199,7 +245,7 @@ div.group-content .group-description { .section-items { display: none; - padding: 5px 20px 10px 20px; + padding: 15px; } .section-items.open { @@ -555,15 +601,6 @@ div.group-content .group-description { transition: all 0.3s ease; } -.just-on-pro { - width: 250px; - height: 100px; - margin-bottom: 10px; - opacity: 0.8; - background: #f5f5f5 url("../images/available_pro.png") no-repeat scroll 0 1px !important; - cursor: not-allowed; -} - .from-web { margin-top: 0; margin-bottom: 15px !important; @@ -645,7 +682,8 @@ input#existing-chart { select#chart-id { float: right; - width: 95px; + width: 146px; + margin-right: 14px; } button#editor-chart-button { @@ -748,16 +786,6 @@ button#editor-chart-button { /* ====== RESPONSIVE ====== */ @media (max-width: 1366px) { - .group-title { - padding: 4px 20px; - font-size: 14px; - font-weight: 400; - } - - .group-title::after { - top: 10px; - } - #rate-stars { margin: 3px 0 10px 40%; } @@ -779,3 +807,192 @@ button#editor-chart-button { vertical-align: middle; } } + +#vz-chart-settings h2:hover, +#vz-chart-review a:hover { + text-decoration: underline; +} + +#vz-chart-review a { + color: #00a0d2; + text-decoration: none; +} + +#vz-chart-settings h2, +#vz-chart-review h2 { + padding: 0; + border: none; + font-size: 12px; + font-weight: 400; +} + +#vz-chart-review { + right: 0; + bottom: 40px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 50%; + padding-right: 20px; + text-align: right; +} + +#vz-chart-settings.bottom-fixed h2 { + padding-left: 20px; +} + +#vz-chart-settings { + bottom: 40px; + left: 0; + -webkit-box-sizing: border-box; + box-sizing: border-box; + width: 50%; + text-align: left; +} + +#vz-chart-review, +#vz-chart-settings h2 { + display: inline; + color: #00a0d2; + background: none; + font-family: "Open Sans",sans-serif; + cursor: pointer; +} + +#vz-chart-settings { + display: inline; + background: none; + cursor: pointer; +} + +#vz-chart-source > ul, +#vz-chart-settings > ul { + position: relative; + z-index: 10; + border-bottom: 1px solid #ddd; +} + +#vz-chart-copyright { + bottom: 10px; + text-align: center; +} + +#sidebar { + border-left: 1px solid #ddd; + background: #f3f3f3; +} + +#vz-chart-settings.open h2 { + position: absolute; + bottom: 28px; + left: 20px; +} + +#vz-chart-settings.open .group-header { + display: block; +} + +#vz-chart-settings .group-header { + display: none; +} + +#vz-csv-file-form, +#vz-one-time-import, +#vz-schedule-import, +.edit-data-content { + text-align: center; +} + +#csv-file { + margin: 15px 0; + padding: 0; +} + +.visualizer-input, +.visualizer-select { + width: 100%; + margin: 0 0 15px; +} + +.group .dashicons-lock { + display: none; +} + +.only-pro-feature .dashicons-lock { + display: inline; +} + +.section-title .dashicons, +.group-title .dashicons { + width: 18px; + height: 18px; + margin-left: 3px; + font-size: 18px; +} + +.only-pro-feature input, +.only-pro-feature button, +.only-pro-feature select { + cursor: not-allowed !important; + pointer-events: none; +} + +.only-pro-feature > div { + position: relative; +} + +.only-pro-content { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + opacity: 0; + background: rgba(253,253,253,0.9); + -webkit-transition: 0.5s ease; + transition: 0.5s ease; +} + +.only-pro-feature:hover .only-pro-content { + opacity: 1; +} + +.only-pro-container { + display: table; + width: 100%; + height: 100%; +} + +.only-pro-inner { + display: table-cell; + vertical-align: middle; +} + +.only-pro-content p { + margin: 0 0 15px; + font-size: 14px; + font-weight: 700; +} + +.only-pro-content a { + display: inline-block; + padding: 7px 12px; + color: #fff; + background: #ff595e; + font-weight: 600; + text-decoration: none; + text-transform: uppercase; + -webkit-transition: 0.1s ease; + transition: 0.1s ease; +} + +.only-pro-content a:hover { + background: #ce484c; +} + +#sidebar::-webkit-scrollbar { + width: 4px; +} + +#sidebar::-webkit-scrollbar-thumb { + background: #999; +} diff --git a/css/library.css b/css/library.css index d95b7b75..817250ed 100644 --- a/css/library.css +++ b/css/library.css @@ -21,10 +21,20 @@ margin: 20px 0 10px; } +.visualizer-list-item .visualizer-pro-only { + text-decoration: line-through; +} + #visualizer-library { + display: table-cell; + width: auto; margin: 20px 0; } +#visualizer-content-wrapper { + width: 100%; +} + .loader { position: absolute; top: 50%; @@ -137,59 +147,139 @@ margin-right: 20px; } -.page-numbers { - padding: 5px 10px; - border-radius: 2px; - color: white !important; - background-color: #aaa; - -webkit-box-shadow: 0 0 5px #ccc; - box-shadow: 0 0 5px #ccc; - font-weight: bold; - text-decoration: none; +#visualizer-search form { + text-align: right; +} + +#visualizer-sidebar { + display: table-cell; + width: 250px; +} + +.visualizer-sidebar-box ul li { + margin: 4px 0; + color: #23282d; +} + +.visualizer-sidebar-box ul { + margin-left: 40px; + text-align: left; + list-style-type: disc; } -.page-numbers.current, -a.page-numbers:hover { - background-color: lightcoral; - -webkit-box-shadow: 0 0 5px lightpink; - box-shadow: 0 0 5px lightpink; +.visualizer-sidebar-box { + display: block; + width: 95%; + margin: 0; + margin-top: 20px; + margin-left: 2.5%; + padding-top: 10px; + padding-bottom: 15px; + border-top: 5px solid #0073aa; + color: #0073aa; + background: white; + text-align: center; +} + +/* The switch - the box around the slider */ +.visualizer-switch { + display: inline-block; + position: relative; + width: 30px; + height: 18px; } -.visualizer-library-pagination { +/* Hide default HTML checkbox */ +.visualizer-switch input { display: none; } -#visualizer-search form { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; +/* The slider */ +.visualizer-tracking sup { + vertical-align: 3px; +} - -webkit-align-items: center; - align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; +.visualizer-slider { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #ccc; + cursor: pointer; + -webkit-transition: 0.4s; + transition: 0.4s; } -#visualizer-search > form > input[type="text"]:nth-child(1) { - height: 30px; +.visualizer-slider:before { + position: absolute; + bottom: 1.5px; + left: 2px; + width: 15px; + height: 15px; + background-color: white; + content: ""; + -webkit-transition: 0.4s; + transition: 0.4s; +} + +input:checked + .visualizer-slider { + background-color: #0085ba; +} + +input:focus + .visualizer-slider { + -webkit-box-shadow: 0 0 1px #0085ba; + box-shadow: 0 0 1px #0085ba; +} + +input:checked + .visualizer-slider:before { + -webkit-transform: translateX(11px); + -ms-transform: translateX(11px); + transform: translateX(11px); +} + +/* Rounded sliders */ +.visualizer-slider.visualizer-round { + border-radius: 34px; +} + +.visualizer-slider.visualizer-round:before { + border-radius: 50%; } -#visualizer-search .button-secondary { - margin-left: 20px; - padding: 5px 10px; - border-radius: 5px; - color: white; - background-color: lightcoral; - -webkit-box-shadow: 0 0 5px lightpink; - box-shadow: 0 0 5px lightpink; +.visualizer-tracking p small sup { + margin-left: -3px; +} + +.visualizer-tracking p { + padding-left: 14px; + color: #23282d; + font-size: 12px; + line-height: 12px; + text-align: left; +} + +.visualizer-tracking span { + margin-left: 10px; + color: #23282d; + background: none; font-size: 14px; font-weight: bold; - line-height: 17px; - text-decoration: none; } -#visualizer-search .button-secondary:hover { - border-color: lightpink; - background-color: lightpink; +#visualizer-content-wrapper { + display: table; +} + +#visualizer-sidebar h3 { + margin-top: 0; +} + +#visualizer-sidebar .visualizer-sidebar-box p { + margin-bottom: 0; +} + +#visualizer-sidebar .visualizer-sidebar-box { + padding-top: 20px; + padding-bottom: 20px; } diff --git a/css/media.css b/css/media.css index 033973ac..e1ea9572 100644 --- a/css/media.css +++ b/css/media.css @@ -1,5 +1,5 @@ /* - Version: 1.7.6 + Version: 2.0.0 */ #visualizer-library-view { padding: 30px 10px 10px 30px; diff --git a/index.php b/index.php index 306895b5..e7265057 100644 --- a/index.php +++ b/index.php @@ -4,47 +4,29 @@ Plugin Name: Visualizer: Charts and Graphs Lite Plugin URI: https://themeisle.com/plugins/visualizer-charts-and-graphs-lite/ Description: A simple, easy to use and quite powerful tool to create, manage and embed interactive charts into your WordPress posts and pages. The plugin uses Google Visualization API to render charts, which supports cross-browser compatibility (adopting VML for older IE versions) and cross-platform portability to iOS and new Android releases. - Version: 1.7.6 + Version: 2.0.0 Author: Themeisle Author URI: http://themeisle.com License: GPL v2.0 or later + WordPress Available: yes + Requires License: no License URI: http://www.opensource.org/licenses/gpl-license.php */ - -// +----------------------------------------------------------------------+ -// | Copyright 2013 Madpixels (email : visualizer@madpixels.net) | -// +----------------------------------------------------------------------+ -// | This program is free software; you can redistribute it and/or modify | -// | it under the terms of the GNU General Public License, version 2, as | -// | published by the Free Software Foundation. | -// | | -// | This program is distributed in the hope that it will be useful, | -// | but WITHOUT ANY WARRANTY; without even the implied warranty of | -// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | -// | GNU General Public License for more details. | -// | | -// | You should have received a copy of the GNU General Public License | -// | along with this program; if not, write to the Free Software | -// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | -// | MA 02110-1301 USA | -// +----------------------------------------------------------------------+ -// | Author: Eugene Manuilov | -// +----------------------------------------------------------------------+ -// prevent direct access to the plugin folder +// Prevent direct access to the plugin folder. if ( ! defined( 'ABSPATH' ) ) { header( 'HTTP/1.0 404 Not Found', true, 404 ); exit; } - // don't load the plugin, if it has been already loaded if ( class_exists( 'Visualizer_Plugin', false ) ) { return; } - // Added by Ash/Upwork if ( class_exists( 'Visualizer_Pro', false ) ) { - define( 'Visualizer_Pro', true ); + define( 'VISUALIZER_PRO', true ); +} else { + defined( 'VISUALIZER_PRO' ) || define( 'VISUALIZER_PRO', false ); } // Added by Ash/Upwork /** @@ -54,6 +36,7 @@ * @since 1.0.0 * * @param string $class The class name to autoload. + * * @return boolean Returns TRUE if the class is located. Otherwise FALSE. */ function visualizer_autoloader( $class ) { @@ -63,6 +46,7 @@ function visualizer_autoloader( $class ) { $filename = dirname( __FILE__ ) . str_replace( '_', DIRECTORY_SEPARATOR, "_classes_{$class}.php" ); if ( is_readable( $filename ) ) { require $filename; + return true; } } @@ -81,46 +65,33 @@ function visualizer_launch() { define( 'VISUALIZER_BASEFILE', __FILE__ ); define( 'VISUALIZER_ABSURL', plugins_url( '/', __FILE__ ) ); define( 'VISUALIZER_ABSPATH', dirname( __FILE__ ) ); - if ( ! defined( 'VISUALIZER_CSV_DELIMITER' ) ) { define( 'VISUALIZER_CSV_DELIMITER', ',' ); } - if ( ! defined( 'VISUALIZER_CSV_ENCLOSURE' ) ) { define( 'VISUALIZER_CSV_ENCLOSURE', '"' ); } - - // don't load the plugin if cron job is running or doing autosave - $doing_autosave = defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE; - $doing_cron = defined( 'DOING_CRON' ) && DOING_CRON; - $doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX; - if ( $doing_autosave || $doing_cron ) { - return; - } - // instantiate the plugin $plugin = Visualizer_Plugin::instance(); - // set general modules $plugin->setModule( Visualizer_Module_Setup::NAME ); $plugin->setModule( Visualizer_Module_Sources::NAME ); - - if ( $doing_ajax ) { - // set ajax modules - $plugin->setModule( Visualizer_Module_Chart::NAME ); + $plugin->setModule( Visualizer_Module_Chart::NAME ); + if ( is_admin() ) { + // set admin modules + $plugin->setModule( Visualizer_Module_Admin::NAME ); } else { - if ( is_admin() ) { - // set admin modules - $plugin->setModule( Visualizer_Module_Admin::NAME ); - } else { - // set frontend modules - $plugin->setModule( Visualizer_Module_Frontend::NAME ); - } + // set frontend modules + $plugin->setModule( Visualizer_Module_Frontend::NAME ); + } + $vendor_file = VISUALIZER_ABSPATH . '/vendor/autoload_52.php'; + if ( is_readable( $vendor_file ) ) { + require_once $vendor_file; + ThemeIsle_SDK_Loader::init_product( VISUALIZER_BASEFILE ); } } // register autoloader function spl_autoload_register( 'visualizer_autoloader' ); - // launch the plugin visualizer_launch(); diff --git a/js/frame.js b/js/frame.js index 9da4330e..3c3c1675 100644 --- a/js/frame.js +++ b/js/frame.js @@ -2,70 +2,79 @@ /* global visualizer */ /* global alert */ -(function($) { - $(document).ready(function() { - $('.type-radio').change(function() { - $('.type-label-selected').removeClass('type-label-selected'); - $(this).parent().addClass('type-label-selected'); - }); - - $('.group-title').click(function() { - var parent = $(this).parent(); - - if (parent.hasClass('open')) { - parent.removeClass('open'); - } else { - $('.group.open').removeClass('open'); - parent.addClass('open'); - } - }); - - $('#remote-file').click(function() { - var url = $.trim(prompt(visualizer.l10n.remotecsv_prompt)); - - if (url !== '') { - if (/^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url)) { - if (url.substr(url.length - 8) === '/pubhtml') { - url = url.substring(0, url.length - 8) + '/export?format=csv'; - } - - $('#remote-data').val(url); - $('#csv-file').val(''); - $('#canvas').lock(); - $('#csv-form').submit(); - } else { - alert(visualizer.l10n.invalid_source); - } - } - }); - - $('#csv-file').change(function() { - if ($.trim($(this).val()) !== '') { - $('#remote-data').val(''); - $('#canvas').lock(); - $('#csv-form').submit(); - } - }); - - $('#thehole').load(function() { - $('#canvas').unlock(); - }); - - $('.section-title').click(function() { - $(this).toggleClass('open').parent().find('.section-items').toggle(); - }); - - $('.more-info').click(function() { - $(this).parent().find('.section-description:first').toggle(); - return false; - }); - - }); +(function ($) { + $(document).ready(function () { + $('.type-radio').change(function () { + $('.type-label-selected').removeClass('type-label-selected'); + $(this).parent().addClass('type-label-selected'); + }); + + $('#vz-chart-settings h2').click(function () { + $("#vz-chart-source").hide(); + $(this).parent().removeClass('bottom-fixed').addClass('open'); + + return false; + }); + $('#vz-chart-settings .customize-section-back').click(function () { + $("#vz-chart-source").show(); + $(this).parent().parent().removeClass('open').addClass('bottom-fixed'); + + return false; + }); + $('.group-title').click(function () { + var parent = $(this).parent(); + + if (parent.hasClass('open')) { + parent.removeClass('open'); + } else { + parent.parent().find('.group.open').removeClass('open'); + parent.addClass('open'); + } + }); + $('#view-remote-file').click(function () { + var url = $(this).parent().find('#remote-data').val(); + + if (url !== '') { + if (/^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url)) { + if (url.substr(url.length - 8) === '/pubhtml') { + url = url.substring(0, url.length - 8) + '/export?format=csv'; + } + + $('#canvas').lock(); + $(this).parent().submit(); + } else { + alert(visualizer.l10n.invalid_source); + } + } + }); + + $('#vz-import-file').click(function (e) { + e.preventDefault(); + if ($.trim($(this).parent().find("#csv-file").val()) !== '') { + $('#canvas').lock(); + $(this).parent().submit(); + } + }); + + $('#thehole').load(function () { + $('#canvas').unlock(); + }); + + $('.section-title').click(function () { + $(this).toggleClass('open').parent().find('.section-items').toggle(); + }); + + $('.more-info').click(function () { + $(this).parent().find('.section-description:first').toggle(); + return false; + }); + + }); })(jQuery); -(function($) { - $.fn.lock = function() { - $(this).each(function() { +(function ($) { + $.fn.lock = function () { + $(this).each(function () { var $this = $(this); var position = $this.css('position'); @@ -73,7 +82,7 @@ position = 'static'; } - switch(position) { + switch (position) { case 'absolute': case 'relative': break; @@ -94,7 +103,7 @@ locker.append(loader); $this.append(locker); - $(window).resize(function() { + $(window).resize(function () { $this.find('.locker,.locker-loader').width($this.width()).height($this.height()); }); }); @@ -102,28 +111,12 @@ return $(this); }; - $.fn.unlock = function() { - $(this).each(function() { + $.fn.unlock = function () { + $(this).each(function () { $(this).find('.locker').remove(); $(this).css('position', $(this).data('position')); }); return $(this); }; -})(jQuery); - -//Hide / show settings in sidebar -(function($) { - $(document).ready(function() { - - $('.advanced-settings-btn').click(function(){ - $('.second-screen, .return-settings-btn').removeClass("hidden-setting"); - $('.initial-screen').addClass("hidden-setting"); - }); - - $('.return-settings-btn').click(function(){ - $('.second-screen, .return-settings-btn').addClass("hidden-setting"); - $('.initial-screen').removeClass("hidden-setting"); - }); - }); -})(jQuery); +})(jQuery); \ No newline at end of file diff --git a/js/library.js b/js/library.js index 5f934004..f04bbe23 100644 --- a/js/library.js +++ b/js/library.js @@ -1,117 +1,128 @@ /* global visualizer */ -(function(wpmv) { - var vm, vmv; +(function (wpmv) { + var vm, vmv; - vm = visualizer.media = {}; - vmv = vm.view = {}; + vm = visualizer.media = {}; + vmv = vm.view = {}; - vmv.Chart = wpmv.MediaFrame.extend({ - initialize: function() { - var self = this; + vmv.Chart = wpmv.MediaFrame.extend({ + initialize: function () { + var self = this; - _.defaults(self.options, { - action: '', - state: 'iframe:visualizer' - }); + _.defaults(self.options, { + action: '', + state: 'iframe:visualizer' + }); - wpmv.MediaFrame.prototype.initialize.apply(self, arguments); + wpmv.MediaFrame.prototype.initialize.apply(self, arguments); - wpmv.settings.tabUrl = self.options.action; - self.createIframeStates(); - }, + wpmv.settings.tabUrl = self.options.action; + self.createIframeStates(); + }, - open: function() { - wpmv.MediaFrame.prototype.open.apply(this, arguments); - this.$el.addClass('hide-menu'); - } - }); + open: function () { + wpmv.MediaFrame.prototype.open.apply(this, arguments); + this.$el.addClass('hide-menu'); + } + }); })(wp.media.view); -(function($, vmv, vu) { - var resizeTimeout; - - $.fn.adjust = function() { - return $(this).each(function() { - var width = $('#visualizer-library').width(), - margin = width * 0.02; - - width *= 0.305; - $(this).width(width - 14).height(width * 0.75).parent().css('margin-right', margin + 'px').css('margin-bottom', margin + 'px'); - }); - }; - - $('.visualizer-chart-canvas').adjust(); - - $(document).ready(function() { - $('.visualizer-chart, .visualizer-library-pagination').fadeIn(500); +(function ($, vmv, vu) { + var resizeTimeout; - $('.visualizer-chart-shortcode').click(function(e) { - var range, selection; + $.fn.adjust = function () { + return $(this).each(function () { + var width = $('#visualizer-library').width(), + margin = width * 0.02; - if (window.getSelection && document.createRange) { - selection = window.getSelection(); - range = document.createRange(); - range.selectNodeContents(e.target); - selection.removeAllRanges(); - selection.addRange(range); - } else if (document.selection && document.body.createTextRange) { - range = document.body.createTextRange(); - range.moveToElementText(e.target); - range.select(); - } - }); + width *= 0.305; + $(this).width(width - 14).height(width * 0.75).parent().css('margin-right', margin + 'px').css('margin-bottom', margin + 'px'); + }); + }; + + $('.visualizer-chart-canvas').adjust(); + + $(document).ready(function () { + $('.visualizer-chart, .visualizer-library-pagination').fadeIn(500); + + $('.visualizer-chart-shortcode').click(function (e) { + var range, selection; + + if (window.getSelection && document.createRange) { + selection = window.getSelection(); + range = document.createRange(); + range.selectNodeContents(e.target); + selection.removeAllRanges(); + selection.addRange(range); + } else if (document.selection && document.body.createTextRange) { + range = document.body.createTextRange(); + range.moveToElementText(e.target); + range.select(); + } + }); - $('.add-new-h2').click(function() { - var wnd = window, - view = new vmv.Chart({action: vu.create}); + $('.add-new-h2').click(function () { + var wnd = window, + view = new vmv.Chart({action: vu.create}); - wnd.send_to_editor = function() { - wnd.location.href = vu.base; - }; - view.open(); + wnd.send_to_editor = function () { + wnd.location.href = vu.base; + }; + view.open(); - return false; - }); + return false; + }); - $('.visualizer-chart-edit').click(function() { - var wnd = window, - view = new vmv.Chart({action: vu.edit + '&chart=' + $(this).attr('data-chart')}); + $('.visualizer-chart-edit').click(function () { + var wnd = window, + view = new vmv.Chart({action: vu.edit + '&chart=' + $(this).attr('data-chart')}); - wnd.send_to_editor = function() { - wnd.location.reload(); - }; + wnd.send_to_editor = function () { + wnd.location.reload(); + }; - view.open(); + view.open(); - return false; - }); + return false; + }); - $(".visualizer-chart-export").on("click", function() { + $(".visualizer-chart-export").on("click", function () { $.ajax({ url: $(this).attr("data-chart"), method: "get", - success: function( data, textStatus, jqXHR ){ + success: function (data, textStatus, jqXHR) { var a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; var blob = new Blob([data.data.csv], {type: "application/csv"}), - url = window.URL.createObjectURL(blob); + url = window.URL.createObjectURL(blob); a.href = url; a.download = data.data.name; a.click(); - setTimeout(function(){ + setTimeout(function () { window.URL.revokeObjectURL(url); }, 100); } }); return false; }); + $('.visualizer-switch input').on('change', function () { - $(window).resize(function() { - clearTimeout(resizeTimeout); - resizeTimeout = setTimeout(function() { - $('.visualizer-chart-canvas').adjust(); - }, 100); - }); - }); + var status = $(this).is(':checked'); + status = (status) ? 'yes' : 'no'; + $.ajax({ + url: visualizer.urls.logger, + data: {status: status}, + method: "get", + success: function (data, textStatus, jqXHR) { + } + }); + }); + $(window).resize(function () { + clearTimeout(resizeTimeout); + resizeTimeout = setTimeout(function () { + $('.visualizer-chart-canvas').adjust(); + }, 100); + }); + }); })(jQuery, visualizer.media.view, visualizer.urls); \ No newline at end of file diff --git a/js/render.js b/js/render.js index b3dddfdd..0ef1b157 100644 --- a/js/render.js +++ b/js/render.js @@ -166,7 +166,7 @@ if (settings.series) { for (i = 0; i < settings.series.length; i++) { format = settings.series[i].format; - if (!format || format === '') { + if (!format || format === '' || !series[i + 1]) { continue; } diff --git a/languages/visualizer.pot b/languages/visualizer.pot index 8691e553..96ef4c0c 100644 --- a/languages/visualizer.pot +++ b/languages/visualizer.pot @@ -2,9 +2,9 @@ # This file is distributed under the GPL v2.0 or later. msgid "" msgstr "" -"Project-Id-Version: Visualizer: Charts and Graphs Lite 1.7.5\n" +"Project-Id-Version: Visualizer: Charts and Graphs Lite 2.0.0\n" "Report-Msgid-Bugs-To: https://github.com/Codeinwp/visualizer/issues\n" -"POT-Creation-Date: 2017-01-20 12:32:52+00:00\n" +"POT-Creation-Date: 2017-04-12 10:19:50+00:00\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -24,188 +24,332 @@ msgstr "" "X-Poedit-Bookmarks: \n" "X-Textdomain-Support: yes\n" -#: classes/Visualizer/Module/Admin.php:77 +#: classes/Visualizer/Module/Admin.php:133 +msgid "Visualizations" +msgstr "" + +#: classes/Visualizer/Module/Admin.php:136 +msgid "From Library" +msgstr "" + +#: classes/Visualizer/Module/Admin.php:137 +msgid "Create New" +msgstr "" + +#: classes/Visualizer/Module/Admin.php:162 msgid "Pie" msgstr "" -#: classes/Visualizer/Module/Admin.php:78 +#: classes/Visualizer/Module/Admin.php:166 msgid "Line" msgstr "" -#: classes/Visualizer/Module/Admin.php:79 +#: classes/Visualizer/Module/Admin.php:170 msgid "Area" msgstr "" -#: classes/Visualizer/Module/Admin.php:80 +#: classes/Visualizer/Module/Admin.php:174 msgid "Geo" msgstr "" -#: classes/Visualizer/Module/Admin.php:81 +#: classes/Visualizer/Module/Admin.php:178 msgid "Bar" msgstr "" -#: classes/Visualizer/Module/Admin.php:82 +#: classes/Visualizer/Module/Admin.php:182 msgid "Column" msgstr "" -#: classes/Visualizer/Module/Admin.php:83 +#: classes/Visualizer/Module/Admin.php:186 msgid "Gauge" msgstr "" -#: classes/Visualizer/Module/Admin.php:84 +#: classes/Visualizer/Module/Admin.php:190 msgid "Scatter" msgstr "" -#: classes/Visualizer/Module/Admin.php:85 +#: classes/Visualizer/Module/Admin.php:194 msgid "Candlestick" msgstr "" -#: classes/Visualizer/Module/Admin.php:87 +#: classes/Visualizer/Module/Admin.php:199 msgid "Table" msgstr "" -#: classes/Visualizer/Module/Admin.php:88 +#: classes/Visualizer/Module/Admin.php:203 msgid "Timeline" msgstr "" -#: classes/Visualizer/Module/Admin.php:89 +#: classes/Visualizer/Module/Admin.php:207 msgid "Combo" msgstr "" -#: classes/Visualizer/Module/Admin.php:157 -msgid "Visualizations" -msgstr "" - -#: classes/Visualizer/Module/Admin.php:160 -msgid "From Library" -msgstr "" - -#: classes/Visualizer/Module/Admin.php:161 -msgid "Create New" -msgstr "" - -#: classes/Visualizer/Module/Admin.php:240 -#: classes/Visualizer/Render/Library.php:168 +#: classes/Visualizer/Module/Admin.php:313 +#: classes/Visualizer/Render/Library.php:42 msgid "Visualizer Library" msgstr "" -#: classes/Visualizer/Module/Admin.php:364 +#: classes/Visualizer/Module/Admin.php:440 msgid "Library" msgstr "" -#: classes/Visualizer/Module/Admin.php:387 +#: classes/Visualizer/Module/Admin.php:465 msgid "Knowledge Base" msgstr "" -#: classes/Visualizer/Module/Admin.php:392 +#: classes/Visualizer/Module/Admin.php:470 msgid "Pro Addon" msgstr "" -#: classes/Visualizer/Module/Chart.php:332 -#: classes/Visualizer/Module/Chart.php:396 -msgid "Please, enter the URL of CSV file:" -msgstr "" - -#: classes/Visualizer/Module/Chart.php:333 -#: classes/Visualizer/Module/Chart.php:397 +#: classes/Visualizer/Module/Chart.php:295 +#: classes/Visualizer/Module/Chart.php:573 msgid "You have entered invalid URL. Please, insert proper URL." msgstr "" -#: classes/Visualizer/Module/Chart.php:411 +#: classes/Visualizer/Module/Chart.php:307 msgid "Save Chart" msgstr "" -#: classes/Visualizer/Module/Chart.php:412 +#: classes/Visualizer/Module/Chart.php:308 msgid "Create Chart" msgstr "" -#: classes/Visualizer/Module/Chart.php:414 +#: classes/Visualizer/Module/Chart.php:310 msgid "Insert Chart" msgstr "" -#: classes/Visualizer/Module/Chart.php:473 +#: classes/Visualizer/Module/Chart.php:407 msgid "CSV file with chart data was not uploaded. Please, try again." msgstr "" -#: classes/Visualizer/Module/Chart.php:488 +#: classes/Visualizer/Module/Chart.php:419 msgid "CSV file is broken or invalid. Please, try again." msgstr "" -#: classes/Visualizer/Render/Library.php:68 +#: classes/Visualizer/Module/Sources.php:142 +msgid "Enable this feature in PRO version!" +msgstr "" + +#: classes/Visualizer/Module/Sources.php:143 +msgid "Buy now" +msgstr "" + +#: classes/Visualizer/Render/Library.php:43 +msgid "Add New" +msgstr "" + +#: classes/Visualizer/Render/Library.php:61 +msgid "" +"%s option is disabled in your php.ini config. Please, enable it by change " +"its value to 1. This option increases the speed of remote CSV uploading." +msgstr "" + +#: classes/Visualizer/Render/Library.php:112 +msgid "Search" +msgstr "" + +#: classes/Visualizer/Render/Library.php:133 +#: classes/Visualizer/Render/Templates.php:85 +msgid "No charts found" +msgstr "" + +#: classes/Visualizer/Render/Library.php:184 #: classes/Visualizer/Render/Templates.php:68 msgid "Delete" msgstr "" -#: classes/Visualizer/Render/Library.php:69 +#: classes/Visualizer/Render/Library.php:185 msgid "Clone" msgstr "" -#: classes/Visualizer/Render/Library.php:70 +#: classes/Visualizer/Render/Library.php:186 msgid "Edit" msgstr "" -#: classes/Visualizer/Render/Library.php:71 +#: classes/Visualizer/Render/Library.php:187 msgid "Export" msgstr "" -#: classes/Visualizer/Render/Library.php:73 +#: classes/Visualizer/Render/Library.php:188 #: classes/Visualizer/Render/Templates.php:71 msgid "Click to select" msgstr "" -#: classes/Visualizer/Render/Library.php:96 -msgid "Search" +#: classes/Visualizer/Render/Library.php:204 +msgid "Gain more editing power" msgstr "" -#: classes/Visualizer/Render/Library.php:140 -#: classes/Visualizer/Render/Templates.php:85 -msgid "No charts found" +#: classes/Visualizer/Render/Library.php:205 +msgid "Spreadsheet like editor" msgstr "" -#: classes/Visualizer/Render/Library.php:169 -msgid "Add New" +#: classes/Visualizer/Render/Library.php:206 +msgid "Import from other charts" msgstr "" -#: classes/Visualizer/Render/Library.php:188 +#: classes/Visualizer/Render/Library.php:207 +msgid "Auto-sync with online files" +msgstr "" + +#: classes/Visualizer/Render/Library.php:208 +msgid "3 more chart types" +msgstr "" + +#: classes/Visualizer/Render/Library.php:209 +msgid "View more features" +msgstr "" + +#: classes/Visualizer/Render/Library.php:217 +msgid "Enable Tracking" +msgstr "" + +#: classes/Visualizer/Render/Library.php:218 msgid "" -"%s option is disabled in your php.ini config. Please, enable it by change " -"its value to 1. This option increases the speed of remote CSV uploading." +"Allow Visualizer to anonymously track how this plugin is used and help us " +"make the plugin better. No sensitive data is tracked." msgstr "" -#: classes/Visualizer/Render/Page/Data.php:70 +#: classes/Visualizer/Render/Page/Data.php:71 +msgid "Chart Data" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:76 +msgid "Import data from file" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:78 msgid "" "Select and upload your data CSV file here. The first row of the CSV file " "should contain the column headings. The second one should contain series " "type (string, number, boolean, date, datetime, timeofday)." msgstr "" -#: classes/Visualizer/Render/Page/Data.php:74 +#: classes/Visualizer/Render/Page/Data.php:79 +#: classes/Visualizer/Render/Page/Data.php:99 msgid "" "If you are unsure about how to format your data CSV then please take a look " -"at this sample:" +"at this sample: %1$s %2$s%3$s" msgstr "" -#: classes/Visualizer/Render/Page/Data.php:76 -msgid "or read how you can add Google spreadsheet in following %1$sarticle%1$s." +#: classes/Visualizer/Render/Page/Data.php:87 +#: classes/Visualizer/Render/Page/Data.php:110 +msgid "Import" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:92 +msgid "Import data from URL" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:95 +msgid "One time import" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:98 +msgid "" +"You can use this to import data from a remote CSV file. The first row of " +"the CSV file should contain the column headings. The second one should " +"contain series type (string, number, boolean, date, datetime, timeofday)." +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:100 +msgid "" +"You can also import data from Google Spreadsheet, for more info check this tutorial" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:105 +#: classes/Visualizer/Render/Page/Data.php:125 +msgid "Please enter the URL of CSV file" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:115 +msgid "Schedule Import" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:118 +msgid "You can choose here to synchronize your chart data with a remote CSV file." +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:119 +msgid "" +"You can also synchronize with your Google Spreadsheet file, for more info " +"check this tutorial" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:120 +msgid "" +"We will update the chart data based on your time interval preference by " +"overwritting the current data with the one from the URL." +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:127 +msgid "How often do you want to check the url" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:132 +msgid "Each hour" msgstr "" -#: classes/Visualizer/Render/Page/Data.php:85 -msgid "From Computer" +#: classes/Visualizer/Render/Page/Data.php:133 +msgid "Each 12 hours" msgstr "" -#: classes/Visualizer/Render/Page/Data.php:88 -msgid "From Web" +#: classes/Visualizer/Render/Page/Data.php:134 +msgid "Each day" msgstr "" -#: classes/Visualizer/Render/Page/Data.php:107 -msgid "Check PRO Version " +#: classes/Visualizer/Render/Page/Data.php:135 +msgid "Each 3 days" msgstr "" -#: classes/Visualizer/Render/Page/Data.php:112 -msgid "Advanced" +#: classes/Visualizer/Render/Page/Data.php:147 +msgid "Save schedule" msgstr "" -#: classes/Visualizer/Render/Page/Data.php:137 +#: classes/Visualizer/Render/Page/Data.php:158 +msgid "Import from other chart" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:162 +msgid "You can import here data from your previously created charts" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:190 +msgid "Import Chart" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:197 +msgid "Edit current data" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:205 +msgid "You can manually edit the chart data using the spreadsheet like editor." +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:207 +msgid "View Editor" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:207 +msgid "Show Chart" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:217 +msgid "Advanced Settings" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:220 +msgid "Chart Settings" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:231 +msgid "Rate our plugin" +msgstr "" + +#: classes/Visualizer/Render/Page/Data.php:250 #: classes/Visualizer/Render/Page/Settings.php:55 msgid "Back" msgstr "" @@ -218,14 +362,6 @@ msgstr "" msgid "Next" msgstr "" -#: classes/Visualizer/Render/Page.php:72 -msgid "Like the plugin? Show us your love!" -msgstr "" - -#: classes/Visualizer/Render/Page.php:75 -msgid "Rate it on WordPress.org" -msgstr "" - #: classes/Visualizer/Render/Sidebar/Columnar.php:42 msgid "Bars Settings" msgstr "" @@ -499,7 +635,7 @@ msgstr "" #: classes/Visualizer/Render/Sidebar/Graph.php:422 #: classes/Visualizer/Render/Sidebar/Graph.php:451 -#: classes/Visualizer/Render/Sidebar.php:526 +#: classes/Visualizer/Render/Sidebar.php:529 msgid "Number Format" msgstr "" @@ -1315,7 +1451,7 @@ msgstr "" msgid "Hex Value" msgstr "" -#: classes/Visualizer/Render/Sidebar.php:529 +#: classes/Visualizer/Render/Sidebar.php:532 msgid "" "Enter custom format pattern to apply to this series value, similar to the " "%1$sICU pattern set%2$s. Use something like #,### to get 1,234 as output, " @@ -1323,11 +1459,11 @@ msgid "" "percentage format then your values will be multiplied by 100." msgstr "" -#: classes/Visualizer/Render/Sidebar.php:537 +#: classes/Visualizer/Render/Sidebar.php:540 msgid "Date Format" msgstr "" -#: classes/Visualizer/Render/Sidebar.php:540 +#: classes/Visualizer/Render/Sidebar.php:543 msgid "" "Enter custom format pattern to apply to this series value, similar to the " "%1$sICU date and time format%2$s." diff --git a/package.json b/package.json index bf2a73c5..9d4c37be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "visualizer", - "version": "1.7.6", + "version": "2.0.0", "description": "Visualizer Lite", "repository": { "type": "git", @@ -10,6 +10,7 @@ "wordpress-plugin" ], "textdomain": "visualizer", + "category": "plugins", "author": "ThemeIsle ", "license": "GPL-2.0+", "bugs": { diff --git a/phpcs.xml b/phpcs.xml index 457b8dae..7872e22d 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -16,11 +16,17 @@ + + + + + + diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..44f0fdb6 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,14 @@ + + + + ./tests/ + + + diff --git a/readme.txt b/readme.txt index db733d01..3aed6576 100644 --- a/readme.txt +++ b/readme.txt @@ -2,32 +2,33 @@ Contributors: codeinwp,marius2012,marius_codeinwp,hardeepasrani,themeisle,Madalin_ThemeIsle Tags: chart, charts, charting, graph, graphs, graphing, visualisation, visualise data, visualization, visualize data, HTML5, canvas, pie chart, line chart, bar chart, column chart, gauge chart, area chart, scatter chart, candlestick chart, geo chart, google visualization api Requires at least: 3.5 -Tested up to: 4.7.1 +Tested up to: 4.7.3 Stable tag: trunk License: GPL v2.0 or later License URI: http://www.opensource.org/licenses/gpl-license.php -A simple and quite powerful WordPress chart plugin to create, manage and embed interactive charts into your WordPress posts and pages. +A simple and quite powerful WordPress chart plugin to create and embed interactive charts & tables into your site. == Description == -WordPress Visualizer plugin is a simple, easy to use and quite powerful tool to create, manage and embed interactive charts into your WordPress posts and pages. +WordPress Visualizer plugin is a simple, easy to use and quite powerful tool to create, manage and embed interactive charts & tables into your WordPress posts and pages. -The plugin uses Google Visualization API to add charts, which support cross-browser compatibility (adopting VML for older IE versions) and cross-platform portability to iOS and new Android releases. +The plugin uses Google Visualization API to add responsive & animated charts/diagrams, which support cross-browser compatibility (adopting VML for older IE versions) and cross-platform portability to iOS and new Android releases. Is the best Excel to WordPress solution who let's you insert charts to your wp site using a simple chart builder. > **Time-saving features available in the Pro version:** > > * Import data from other charts > * Easy edit the data using a live editor > * 3 more chart types ( Combo, Timeline and Table chart ) +> * Auto synchronize with your online file. > * Priority email support from the developer of the plugin > * Support and updates for 1 year > -> **[Learn more about Visualizer PRO](http://themeisle.com/plugins/visualizer-charts-and-graphs-pro-addon/)** +> **[Learn more about Visualizer PRO](http://themeisle.com/plugins/visualizer-charts-and-graphs/)** ### 9 Chart types + 3 more in the pro version ### -This WordPress graph plugin provides a variety of charts that are optimized to address your WordPress data visualization needs. It is line chart, area chart, bar chart, column chart, pie chart, geo chart, gauge chart, candlestick chart and scatter chart. These charts are based on pure HTML5/SVG technology (adopting VML for old IE versions), so no extra plugins are required. Adding these charts to your page can be done in a few simple steps. +This WordPress graph plugin provides a variety of charts that are optimized to address your WordPress data visualization needs. It is line chart,flow chart, area chart, bar chart, column chart, pie chart, geo chart, gauge chart, candlestick chart and scatter chart. These charts are based on pure HTML5/SVG technology (adopting VML for old IE versions), so no extra plugins are required. Adding these charts to your page can be done in a few simple steps. The premium version can act as a interactive WordPress Table plugin, with sorting capabilities. ### Flexible and customizable ### Make the charts your own. Configure an extensive set of options to perfectly match the look and feel of your website. You can use Google Chart Tools with their default setting - all customization is optional and the basic setup is launch-ready. However, charts can be easily customizable in case your webpage adopts a style which is at odds with provided defaults. Every chart exposes a number of options that customize its look and feel. @@ -39,15 +40,22 @@ Charts are rendered using HTML5/SVG technology to provide cross-browser compatib The plugins works perfectly with the all free or premium WordPress themes -### Knowledge Base ### -1. [How can I create a chart?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-create-a-chart%3F) -1. [How can I edit a chart?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-edit-a-chart%3F) -1. [How can I clone a chart?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-clone-a-chart%3F) -1. [How can I delete a chart?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-delete-a-chart%3F) -1. [How can I highlight a single bar?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-highlight-a-single-bar%3F) -1. [How can I populate chart series and data dynamically?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-populate-chart-series-and-data-dynamically%3F) -1. [How can I populate data from Google Spreadsheet?](https://github.com/madpixelslabs/visualizer/wiki/How-can-I-populate-data-from-Google-Spreadsheet%3F) + = See how Visualizer can integrate with your website = + +* [Create line chart ](https://demo.themeisle.com/visualizer/line-chart/) +* [Create pie chart ](https://demo.themeisle.com/visualizer/pie-chart/) +* [Create bar chart](https://demo.themeisle.com/visualizer/bar-chart/) +* [Create column chart](https://demo.themeisle.com/visualizer/column-chart/) +* [Create area chart](https://demo.themeisle.com/visualizer/area-chart/) +* [Create geo chart](https://demo.themeisle.com/visualizer/geo-chart/) +* [Create table chart](https://demo.themeisle.com/visualizer/table-chart/) +* [Create gauge chart](https://demo.themeisle.com/visualizer/gauge-chart//) +* [Create candlestick chart](https://demo.themeisle.com/visualizer/candlestick-chart/) +* [Create combo chart](https://demo.themeisle.com/visualizer/combo-chart/) +* [Create scatter chart](https://demo.themeisle.com/visualizer/scatter-chart/) +* [Create timeline chart](https://demo.themeisle.com/visualizer/timeline-chart/) + == Installation == @@ -60,6 +68,46 @@ The plugins works perfectly with the all ` call at the bottom of **footer.php** file. += How can I create a chart? = + +http://docs.themeisle.com/article/597-create-chart + += How can I edit a chart? = + +http://docs.themeisle.com/article/602-how-can-i-edit-a-chart + += How can I delete a chart? = + +http://docs.themeisle.com/article/600-delete-chart + += How can I clone a chart? = + +http://docs.themeisle.com/article/598-clone-chart + += How can I highlight a single bar? = + +http://docs.themeisle.com/article/603-how-can-i-highlight-a-single-bar + += How can I populate chart series and data dynamically? = + +http://docs.themeisle.com/article/605-how-can-i-populate-chart-series-and-data-dynamically + += How can I populate data from Google Spreadsheet? = + +http://docs.themeisle.com/article/607-how-can-i-populate-data-from-google-spreadsheet + += How can i import content from another chart? = + +http://docs.themeisle.com/article/609-how-can-i-import-content-from-another-chart + += How to export a chart? = + +http://docs.themeisle.com/article/608-how-to-export-a-chart + += How can i edit the data manually? = + +http://docs.themeisle.com/article/610-how-can-i-edit-the-data-manually + == Screenshots == 1. Chart type selection @@ -70,29 +118,34 @@ Pay attention that to turn your shortcodes into graphs, your theme has to have ` == Changelog == -= 1.7.6= += 2.0.0 = +* Improved design and layout to support multiple datasources. +* Added new integrations in the Pro version. +* Added opt-in for tracking. + += 1.7.6 = * Fixed issue when using the same shortcode multiple times on the same page. -= 1.7.5= += 1.7.5 = * Removed footer banner upsell * Fixed series settings issue * Fixed issue with comas being used in numbers -= 1.7.2= += 1.7.2 = * Improved charts responsive system -= 1.7.1= += 1.7.1 = * Fixed grid lines error links -= 1.7.0= += 1.7.0 = * Fixed responsive issues * Fixed issues with zero margin values * Fixed import issue -= 1.6.6= += 1.6.6 = * Fixed charts resizing on tabbed content -= 1.6.5= += 1.6.5 = * Fixed responsive issue * Fixed no axis text color for line and bar charts @@ -208,4 +261,4 @@ Pay attention that to turn your shortcodes into graphs, your theme has to have ` * The bug with CSV file uploading was fixed. = 1.0.0 = -* The first version of the plugin was implemented. +* The first version of what wil be the best wp charts plugin. diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 00000000..137e4df8 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,54 @@ +set_role( 'administrator' ); +wp_update_user( array( + 'ID' => 1, + 'first_name' => 'Admin', + 'last_name' => 'User', +) ); diff --git a/tests/test-export.php b/tests/test-export.php new file mode 100644 index 00000000..cb4fbe7d --- /dev/null +++ b/tests/test-export.php @@ -0,0 +1,90 @@ +_setRole( 'administrator' ); + + $_GET = array( + 'library' => 'yes', + 'tab' => 'visualizer', + ); + + // swallow the output + ob_start(); + try { + $this->_handleAjax( 'visualizer-create-chart' ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } catch ( WPAjaxDieStopException $ee ) { + // We expected this, do nothing. + } + ob_end_clean(); + + $query = new WP_Query(array( + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, + 'post_status' => 'auto-draft', + 'numberposts' => 1, + 'fields' => 'ids', + )); + $this->chart = $query->posts[0]; + } + + /** + * Testing export + * + * @access public + */ + public function test_download_export() { + $this->create_chart(); + $this->_setRole( 'administrator' ); + + $_GET = array( + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_EXPORT_DATA . Visualizer_Plugin::VERSION ), + 'chart' => $this->chart, + ); + + // swallow the output + ob_start(); + try { + $this->_handleAjax( 'visualizer-export-data' ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } catch ( WPAjaxDieStopException $ee ) { + // We expected this, do nothing. + } + ob_end_clean(); + + $response = json_decode( $this->_last_response ); + $this->assertInternalType( 'object', $response ); + $this->assertObjectHasAttribute( 'success', $response ); + $this->assertObjectHasAttribute( 'data', $response ); + $this->assertTrue( $response->success ); + } +} diff --git a/tests/test-import.php b/tests/test-import.php new file mode 100644 index 00000000..89216922 --- /dev/null +++ b/tests/test-import.php @@ -0,0 +1,227 @@ +markTestSkipped( 'this test is disabled till we can figure out how to provide a "local" url' ); + $this->create_chart(); + $this->_setRole( 'administrator' ); + $_POST = array( + 'remote_data' => $url, + ); + $_GET = array( + 'nonce' => wp_create_nonce(), + 'chart' => $this->chart, + ); + // swallow the output + ob_start(); + try { + $this->_handleAjax( 'visualizer-upload-data' ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } catch ( WPAjaxDieStopException $ee ) { + // We expected this, do nothing. + } + ob_end_clean(); + $series_new = get_post_meta( $this->chart, 'visualizer-series', true ); + $chart = get_post( $this->chart ); + $src = get_post_meta( $this->chart, 'visualizer-source', true ); + $content_new = $chart->post_content; + $this->assertEquals( 'Visualizer_Source_Csv_Remote', $src ); + $this->assertEquals( $content_new, serialize( $content ) ); + $this->assertEquals( $series_new, $series ); + } + + /** + * Create a chart + * + * @since 2.0.0 + * + * @access private + */ + private function create_chart() { + $this->_setRole( 'administrator' ); + $_GET = array( + 'library' => 'yes', + 'tab' => 'visualizer', + ); + // swallow the output + ob_start(); + try { + $this->_handleAjax( 'visualizer-create-chart' ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } catch ( WPAjaxDieStopException $ee ) { + // We expected this, do nothing. + } + ob_end_clean(); + $query = new WP_Query( array( + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER, + 'post_status' => 'auto-draft', + 'numberposts' => 1, + 'fields' => 'ids', + ) ); + $this->chart = $query->posts[0]; + } + + /** + * Testing file import feature. + * + * @access public + * @dataProvider fileProvider + */ + public function test_file_import( $file, $content, $series ) { + $this->create_chart(); + $this->_setRole( 'administrator' ); + $dest = dirname( __FILE__ ) . DIRECTORY_SEPARATOR . basename( $file ); + copy( $file, $dest ); + $_FILES = array( + 'local_data' => array( + 'tmp_name' => $dest, + 'error' => 0, + ), + ); + $_GET = array( + 'nonce' => wp_create_nonce(), + 'chart' => $this->chart, + ); + // swallow the output + ob_start(); + try { + $this->_handleAjax( 'visualizer-upload-data' ); + } catch ( WPAjaxDieContinueException $e ) { + // We expected this, do nothing. + } catch ( WPAjaxDieStopException $ee ) { + // We expected this, do nothing. + } + ob_end_clean(); + unlink( $dest ); + $series_new = get_post_meta( $this->chart, 'visualizer-series', true ); + $chart = get_post( $this->chart ); + $src = get_post_meta( $this->chart, 'visualizer-source', true ); + $content_new = $chart->post_content; + $this->assertEquals( 'Visualizer_Source_Csv', $src ); + $this->assertEquals( $content_new, serialize( $content ) ); + $this->assertEquals( $series_new, $series ); + } + + /** + * Provide the fileURL for uploading the file + * + * @access public + */ + public function fileProvider() { + $file = VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . 'bar.csv'; + list( $content, $series ) = $this->parseFile( $file ); + + return array( + array( $file, $content, $series ), + ); + } + + /** + * Provide the parsed (and manipulated, if required) data for the specific data file + * + * @access private + */ + private function parseFile( $file, $multiplyValuesBy = 1 ) { + $file = $file; + ini_set( 'auto_detect_line_endings', true ); + $handle = fopen( $file, 'rb' ); + // read column titles + $labels = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ); + // read series types + $types = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ); + $_series = array(); + for ( $i = 0, $len = count( $labels ); $i < $len; $i ++ ) { + $default_type = $i == 0 ? 'string' : 'number'; + $_series[] = array( + 'label' => $labels[ $i ], + 'type' => isset( $types[ $i ] ) ? $types[ $i ] : $default_type, + ); + } + $_content = array(); + while ( ( $data = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ) ) !== false ) { + foreach ( $_series as $i => $series ) { + // if no value exists for the seires, then add null + if ( ! isset( $data[ $i ] ) ) { + $data[ $i ] = null; + } + if ( is_null( $data[ $i ] ) ) { + continue; + } + switch ( $series['type'] ) { + case 'number': + $data[ $i ] = ( is_numeric( $data[ $i ] ) ) ? floatval( $data[ $i ] * $multiplyValuesBy ) : ( is_numeric( str_replace( ',', '', $data[ $i ] ) ) ? floatval( ( str_replace( ',', '', $data[ $i ] ) ) * $multiplyValuesBy ) : null ); + break; + case 'boolean': + $data[ $i ] = ! empty( $data[ $i ] ) ? filter_validate( $data[ $i ], FILTER_VALIDATE_BOOLEAN ) : null; + break; + case 'timeofday': + $date = new DateTime( '1984-03-16T' . $data[ $i ] ); + if ( $date ) { + $data[ $i ] = array( + intval( $date->format( 'H' ) ), + intval( $date->format( 'i' ) ), + intval( $date->format( 's' ) ), + 0, + ); + } + break; + } + } + $_content[] = $data; + } + fclose( $handle ); + + return array( $_content, $_series ); + } + + /** + * Provide the URL for uploading the file + * + * @access public + */ + public function urlProvider() { + $url = 'https://demo.themeisle.com/wp-content/plugins/visualizer/samples/bar.csv'; + $file = download_url( $url ); + list( $content, $series ) = $this->parseFile( $file ); + unlink( $file ); + + return array( + array( + $url, + array( + 'source' => $url, + 'data' => $content, + ), + $series, + ), + ); + } +}