Example #1
0
 public function init()
 {
     $meta = $this->getMeta();
     if (!empty($meta)) {
         DatawrapperVisualization::register($this, $meta);
     }
 }
 public static function getInstance()
 {
     if (!isset(self::$instance)) {
         self::$instance = new DatawrapperVisualization();
     }
     return self::$instance;
 }
Example #3
0
 public function dashboard($app, $page)
 {
     // returns a CSV from a MySQL resultset
     function res2csv($rs)
     {
         $csv = "";
         $keys = array();
         $results = array();
         foreach ($rs as $r) {
             if (count($keys) == 0) {
                 foreach ($r as $key => $val) {
                     if (is_string($key)) {
                         $keys[] = $key;
                     }
                 }
                 $csv = implode(";", $keys) . "\\n";
             }
             $results[] = $r;
         }
         $results = array_reverse($results);
         foreach ($results as $r) {
             $values = array();
             foreach ($keys as $key) {
                 $values[] = $r[$key];
             }
             $csv .= implode(";", $values) . "\\n";
         }
         return $csv;
     }
     $con = Propel::getConnection();
     $data = array();
     $publised_sql = 'SELECT DATE_FORMAT(published_at, \'%Y-%m-%d\') pub_date, COUNT(*) pub_count FROM `chart` WHERE last_edit_step = 5 GROUP BY pub_date ORDER BY `pub_date` DESC LIMIT 1,90';
     $publised_week_sql = 'SELECT DATE_FORMAT(published_at, \'%Y-w%u\') pub_date, COUNT(*) pub_count FROM `chart` WHERE last_edit_step = 5 GROUP BY pub_date ORDER BY `pub_date` DESC LIMIT 1,26';
     $user_signups_sql = 'SELECT DATE_FORMAT(created_at, \'%Y-%m-%d\') create_date, COUNT(*) user_count FROM `user` GROUP BY create_date ORDER BY `create_date` DESC LIMIT 1,90';
     $numUsers = UserQuery::create()->filterByDeleted(false)->count();
     $numUsersPending = UserQuery::create()->filterByDeleted(false)->filterByRole(UserPeer::ROLE_PENDING)->count();
     $numUsersActivated = UserQuery::create()->filterByDeleted(false)->filterByRole(UserPeer::ROLE_EDITOR)->count();
     $numUsersDeleted = UserQuery::create()->filterByDeleted(true)->count();
     $users_csv = "Type;Count\\nPending;{$numUsersPending}\\nActivated;{$numUsersActivated}\\nDeleted;{$numUsersDeleted}";
     $numCharts = ChartQuery::create()->filterByDeleted(false)->count();
     $numChartsUpload = ChartQuery::create()->filterByLastEditStep(array('max' => 1))->filterByDeleted(false)->count();
     $numChartsDescribe = ChartQuery::create()->filterByLastEditStep(2)->filterByDeleted(false)->count();
     $numChartsVisualize = ChartQuery::create()->filterByLastEditStep(3)->filterByDeleted(false)->count();
     $numChartsPublished = ChartQuery::create()->filterByLastEditStep(array('min' => 4))->filterByDeleted(false)->count();
     $charts_csv = "LastEditStep;Count\\nUpload;{$numChartsUpload}\\nDescribe;{$numChartsDescribe}\\nVisualize;{$numChartsVisualize}\\nPublish;{$numChartsPublished}\\n";
     $charts_by_type_csv = res2csv($con->query('SELECT type, COUNT(*) FROM chart WHERE deleted = 0 GROUP BY type;'));
     $charts_by_type_csv = str_replace('-chart', '', $charts_by_type_csv);
     $page = array_merge($page, array('num_users' => $numUsers, 'num_users_activated' => $numUsersActivated, 'num_charts' => $numCharts, 'num_charts_published' => $numChartsPublished, 'published_csv' => res2csv($con->query($publised_sql)), 'published_week_csv' => res2csv($con->query($publised_week_sql)), 'users_csv' => $users_csv, 'charts_edit_step_csv' => $charts_csv, 'charts_by_type_csv' => $charts_by_type_csv, 'created_csv' => res2csv($con->query('SELECT DATE_FORMAT(created_at, \'%Y-%m-%d\') pub_date, COUNT(*) pub_count FROM `chart` GROUP BY pub_date ORDER BY `pub_date` DESC LIMIT 1,90')), 'created_weekly_csv' => res2csv($con->query('SELECT DATE_FORMAT(created_at, \'%Y-w%u\') pub_date, COUNT(*) pub_count FROM `chart` GROUP BY pub_date ORDER BY `pub_date` DESC LIMIT 1,26')), 'user_signups_csv' => res2csv($con->query($user_signups_sql)), 'linechart' => DatawrapperVisualization::get('line-chart'), 'columnchart' => DatawrapperVisualization::get('column-chart'), 'donutchart' => DatawrapperVisualization::get('donut-chart'), 'chartLocale' => 'en-US'));
     $app->render('plugins/admin-dashboard/admin-dashboard.twig', $page);
 }
Example #4
0
 public function nbChartsByType()
 {
     $con = Propel::getConnection();
     $sql = "SELECT type, COUNT(*) c FROM chart WHERE show_in_gallery = 1 AND last_edit_step >= 4 and deleted = 0 GROUP BY type ORDER BY c DESC ;";
     $rs = $con->query($sql);
     $res = array();
     $max = 0;
     foreach ($rs as $r) {
         $vis = DatawrapperVisualization::get($r['type']);
         $lang = substr(DatawrapperSession::getLanguage(), 0, 2);
         $res[] = array('count' => $r['c'], 'id' => $r['type'], 'name' => $vis['title']);
         $max = max($max, $r['c']);
     }
     foreach ($res as $c => $r) {
         $res[$c]['bar'] = round($r['count'] / $max * 80);
     }
     return $res;
 }
Example #5
0
function nbChartsByType($user)
{
    $con = Propel::getConnection();
    $sql = "SELECT type, COUNT(*) c FROM chart WHERE author_id = " . $user->getId() . " AND deleted = 0 AND last_edit_step >= 2 GROUP BY type ORDER BY c DESC ;";
    $rs = $con->query($sql);
    $res = array();
    foreach ($rs as $r) {
        $vis = DatawrapperVisualization::get($r['type']);
        $lang = substr(DatawrapperSession::getLanguage(), 0, 2);
        if (!isset($vis['title'])) {
            continue;
        }
        if (empty($vis['title'][$lang])) {
            $lang = 'en';
        }
        $res[] = array('count' => $r['c'], 'id' => $r['type'], 'name' => $vis['title']);
    }
    return $res;
}
Example #6
0
 public function init()
 {
     $meta = $this->getMeta();
     $datasets = $this->getDemoDataSets();
     $demo_hook = DatawrapperHooks::GET_DEMO_DATASETS;
     if (!empty($meta)) {
         DatawrapperVisualization::register($this, $meta);
     }
     if (!empty($datasets)) {
         $first_element = reset($datasets);
         if (is_array($first_element)) {
             foreach ($datasets as $key => $dataset) {
                 DatawrapperHooks::register($demo_hook, function () use($dataset) {
                     return $dataset;
                 });
             }
         } else {
             DatawrapperHooks::register($demo_hook, function () use($datasets) {
                 return $datasets;
             });
         }
     }
 }
Example #7
0
function publish_css($user, $chart)
{
    $cdn_files = array();
    $static_path = get_static_path($chart);
    $data = get_chart_content($chart, $user, false, '../');
    $all = '';
    foreach ($data['stylesheets'] as $css) {
        $all .= file_get_contents(ROOT_PATH . 'www' . $css) . "\n\n";
    }
    // move @imports to top of file
    $imports = array();
    $body = "";
    $lines = explode("\n", $all);
    foreach ($lines as $line) {
        if (substr($line, 0, 7) == '@import') {
            $imports[] = $line;
        } else {
            $body .= $line . "\n";
        }
    }
    $all = implode("\n", $imports) . "\n\n" . $body;
    $cssmin = new CSSmin();
    $minified = $all;
    //$cssmin->run($all); disabled minification
    file_put_contents($static_path . "/" . $chart->getID() . '.all.css', $minified);
    $cdn_files[] = array($static_path . "/" . $chart->getID() . '.all.css', $chart->getCDNPath() . $chart->getID() . '.all.css', 'text/css');
    // copy themes assets
    $theme = $data['theme'];
    if (isset($theme['assets'])) {
        foreach ($theme['assets'] as $asset) {
            $asset_src = '../../www/' . $theme['__static_path'] . '/' . $asset;
            $asset_tgt = $static_path . "/" . $asset;
            if (file_exists($asset_src)) {
                file_put_contents($asset_tgt, file_get_contents($asset_src));
                $cdn_files[] = array($asset_src, $chart->getCDNPath() . $asset);
            }
        }
    }
    // copy visualization assets
    $vis = $data['visualization'];
    $assets = DatawrapperVisualization::assets($vis['id'], $chart);
    foreach ($assets as $asset) {
        $asset_src = ROOT_PATH . 'www/static/' . $asset;
        $asset_tgt = $static_path . '/assets/' . $asset;
        create_missing_directories($asset_tgt);
        copy($asset_src, $asset_tgt);
        $cdn_files[] = array($asset_src, $chart->getCDNPath() . 'assets/' . $asset);
    }
    return $cdn_files;
}
Example #8
0
 */
$app->get('/xhr/header/:page', function ($active) use($app) {
    disable_cache($app);
    $page = array();
    add_header_vars($page, $active);
    $res = $app->response();
    $res['Cache-Control'] = 'max-age=0';
    $app->render('header.twig', $page);
});
/**
 * reloads the header menu after login/logout
 */
$app->get('/xhr/home-login', function () use($app) {
    $page = array();
    add_header_vars($page);
    $res = $app->response();
    $res['Cache-Control'] = 'max-age=0';
    $app->render('home-login.twig', $page);
});
/**
 * reloads visualization specific options after the user
 * changed the visualization type
 */
require_once '../lib/utils/themes.php';
$app->get('/xhr/:chartid/vis-options', function ($id) use($app) {
    disable_cache($app);
    check_chart_writable($id, function ($user, $chart) use($app) {
        $page = array('vis' => DatawrapperVisualization::get($chart->getType()), 'theme' => DatawrapperTheme::get($chart->getTheme()), 'language' => substr(DatawrapperSession::getLanguage(), 0, 2));
        $app->render('vis-options.twig', $page);
    });
});
function get_chart_content($chart, $user, $published = false, $debug = false)
{
    $theme_css = array();
    $theme_js = array();
    $next_theme_id = $chart->getTheme();
    $locale = DatawrapperSession::getLanguage();
    while (!empty($next_theme_id)) {
        $theme = DatawrapperTheme::get($next_theme_id);
        $theme_js[] = $theme['__static_path'] . $next_theme_id . '.js';
        if ($theme['hasStyles']) {
            $theme_css[] = $theme['__static_path'] . $next_theme_id . '.css';
        }
        $next_theme_id = $theme['extends'];
    }
    $abs = 'http://' . $GLOBALS['dw_config']['domain'];
    $debug = $GLOBALS['dw_config']['debug'] == true || $debug;
    if ($published && !$debug) {
        $base_js = array('//assets-datawrapper.s3.amazonaws.com/globalize.min.js', '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.2/underscore-min.js', '//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js');
        if (substr($locale, 0, 2) != 'en') {
            $base_js[] = '//assets-datawrapper.s3.amazonaws.com/cultures/globalize.culture.' . str_replace('_', '-', $locale) . '.js';
        }
    } else {
        // use local assets
        $base_js = array($abs . '/static/vendor/globalize/globalize.min.js', $abs . '/static/vendor/underscore/underscore-min.js', $abs . '/static/vendor/jquery/jquery-1.9.1' . ($debug ? '' : '.min') . '.js');
        if (substr($locale, 0, 2) != 'en') {
            $base_js[] = $abs . '/static/vendor/globalize/cultures/globalize.culture.' . str_replace('_', '-', $locale) . '.js';
        }
    }
    $vis_js = array();
    $vis_css = array();
    $next_vis_id = $chart->getType();
    $vis_libs = array();
    $vis_locale = array();
    // visualizations may define localized strings, e.g. "other"
    while (!empty($next_vis_id)) {
        $vis = DatawrapperVisualization::get($next_vis_id);
        $vjs = array();
        if (!empty($vis['libraries'])) {
            foreach ($vis['libraries'] as $url) {
                // at first we check if the library lives in ./lib of the vis module
                if (file_exists(ROOT_PATH . 'www/' . $vis['__static_path'] . $url)) {
                    $vis_libs[] = $vis['__static_path'] . $url;
                } else {
                    if (file_exists(ROOT_PATH . 'www/static/vendor/' . $url)) {
                        $vis_libs[] = '/static/vendor/' . $url;
                    }
                }
            }
        }
        if (!empty($vis['locale']) && is_array($vis['locale'])) {
            foreach ($vis['locale'] as $term => $translations) {
                if (!isset($vis_locale[$term])) {
                    $vis_locale[$term] = $translations;
                }
            }
        }
        $vjs[] = $vis['__static_path'] . $vis['id'] . '.js';
        $vis_js = array_merge($vis_js, array_reverse($vjs));
        if ($vis['hasCSS']) {
            $vis_css[] = $vis['__static_path'] . $vis['id'] . '.css';
        }
        $next_vis_id = !empty($vis['extends']) ? $vis['extends'] : null;
    }
    $styles = array_merge($vis_css, array_reverse($theme_css));
    $the_vis = DatawrapperVisualization::get($chart->getType());
    $the_vis['locale'] = $vis_locale;
    $the_theme = DatawrapperTheme::get($chart->getTheme());
    if ($published) {
        $scripts = array_merge($base_js, array('/lib/vis/' . $the_vis['id'] . '-' . $the_vis['version'] . '.min.js', '/lib/theme/' . $the_theme['id'] . '-' . $the_theme['version'] . '.min.js'));
        $styles = array($chart->getID() . '.min.css');
        $the_vis['__static_path'] = '';
        $the_theme['__static_path'] = '';
    } else {
        $scripts = array_unique(array_merge($base_js, array('/static/js/datawrapper' . ($debug ? '' : '.min') . '.js'), array_reverse($theme_js), array_reverse($vis_js), $vis_libs));
    }
    $cfg = $GLOBALS['dw_config'];
    $published_urls = DatawrapperHooks::execute(DatawrapperHooks::GET_PUBLISHED_URL, $chart);
    if (empty($published_urls)) {
        $chart_url = 'http://' . $cfg['chart_domain'] . '/' . $chart->getID() . '/';
    } else {
        $chart_url = $published_urls[0];
        // ignore urls except from the first one
    }
    $page = array('chartData' => $chart->loadData(), 'chart' => $chart, 'chartLocale' => str_replace('_', '-', $locale), 'lang' => strtolower(substr($locale, 0, 2)), 'metricPrefix' => get_metric_prefix($locale), 'theme' => $the_theme, 'l10n__domain' => $the_theme['__static_path'], 'visualization' => $the_vis, 'stylesheets' => $styles, 'scripts' => $scripts, 'themeJS' => array_reverse($theme_js), 'visJS' => array_merge(array_reverse($vis_js), $vis_libs), 'origin' => !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', 'DW_DOMAIN' => 'http://' . $cfg['domain'] . '/', 'DW_CHART_DATA' => 'http://' . $cfg['domain'] . '/chart/' . $chart->getID() . '/data', 'ASSET_PATH' => $published ? '' : $the_theme['__static_path'], 'trackingCode' => !empty($analyticsMod) ? $analyticsMod->getTrackingCode($chart) : '', 'chartUrl' => $chart_url, 'embedCode' => '<iframe src="' . $chart_url . '" frameborder="0" allowtransparency="true" allowfullscreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen width="' . $chart->getMetadata('publish.embed-width') . '" height="' . $chart->getMetadata('publish.embed-height') . '"></iframe>', 'chartUrlFs' => strpos($chart_url, '.html') > 0 ? str_replace('index.html', 'fs.html', $chart_url) : $chart_url . '?fs=1');
    return $page;
}
Example #10
0
<?php

$asset_domain = $GLOBALS['dw_config']['asset_domain'];
$asset_url = '//' . $asset_domain . '/';
DatawrapperVisualization::register($plugin, array("id" => "raphael-chart", "libraries" => array(array("local" => "vendor/d3-light.min.js", "cdn" => !empty($asset_domain) ? $asset_url . "vendor/d3-light/3.1.8/d3-light.min.js" : null), array("local" => "vendor/chroma.min.js", "cdn" => !empty($asset_domain) ? $asset_url . "vendor/chroma-js/0.5.4/chroma.min.js" : null), array("local" => "vendor/raphael-2.1.2.min.js", "cdn" => !empty($asset_domain) ? $asset_url . "vendor/raphael-js/2.1.2/raphael-min.js" : null))));
Example #11
0
<?php

DatawrapperVisualization::register($plugin, array('id' => 'pie-chart', 'title' => __('Pie chart'), 'extends' => 'raphael-chart', 'author' => array('name' => 'gka', 'email' => '*****@*****.**'), 'order' => 50, 'dimensions' => 1, 'axes' => array('labels' => array('accepts' => array('text', 'date')), 'slices' => array('accepts' => array('number'), 'multiple' => true)), 'color-by' => 'row', 'options' => array('base-color' => array('type' => 'base-color', 'label' => __('Base color')), 'group-slice-after' => array('type' => 'number', 'label' => __('Maximum amount of slices'), 'default' => '5', 'depends-on' => array('chart.min_row_num' => 3), 'min' => 2, 'max' => 100)), 'locale' => array('other' => __('other'), 'cannotShowNegativeValues' => __('Pie charts are intended to show part-of-whole relations, and thus they <b>cannot be used to display negative numbers</b>. Please consider using a different chart type instead (eg. a bar chart).'), 'noMoreThanFiveSlices' => __('Your data contains <b>more values than can be shown in a pie chart</b>, so we grouped %count slices into the slice named <i>"others"</i>.<p>Why not use a bar chart to allow better comparison of values?</p>')), 'libraries' => array()));
DatawrapperVisualization::register($plugin, array('id' => 'donut-chart', 'title' => __('Donut chart'), 'version' => '1.3.0', 'extends' => 'pie-chart', 'author' => array('name' => 'gka', 'email' => '*****@*****.**'), 'order' => 60, 'dimensions' => 1, 'axes' => array('labels' => array('accepts' => array('text', 'date')), 'slices' => array('accepts' => array('number'), 'multiple' => true)), 'options' => array('base-color' => array('type' => 'base-color', 'label' => __('Base color')), 'show-total' => array('type' => 'checkbox', 'label' => __('Show total value in center'), 'default' => true), 'custom-total' => array('type' => 'checkbox', 'label' => __('Use custom total value instead of sum'), 'default' => false, 'depends-on' => array('show-total' => true, 'chart.max_row_num' => 1)), 'custom-total-value' => array('type' => 'text', 'label' => __('Custom total value'), 'depends-on' => array('show-total' => true, 'custom-total' => true)), 'group-slice-after' => array('type' => 'number', 'label' => __('Maximum amount of slices'), 'default' => '5', 'depends-on' => array('chart.min_row_num' => 3), 'min' => 2, 'max' => 100))));
Example #12
0
<?php

/*
 * VISUALIZE STEP
 */
$app->get('/chart/:id/visualize', function ($id) use($app) {
    disable_cache($app);
    check_chart_writable($id, function ($user, $chart) use($app) {
        $page = array('title' => $chart->getID() . ' :: ' . __('Visualize'), 'chartData' => $chart->loadData(), 'chart' => $chart, 'visualizations_deps' => DatawrapperVisualization::all('dependencies'), 'visualizations' => DatawrapperVisualization::all(), 'vis' => DatawrapperVisualization::get($chart->getType()), 'themes' => DatawrapperTheme::all(), 'theme' => DatawrapperTheme::get($chart->getTheme()), 'debug' => !empty($GLOBALS['dw_config']['debug_export_test_cases']) ? '1' : '0');
        add_header_vars($page, 'chart');
        add_editor_nav($page, 3);
        $app->render('chart/visualize.twig', $page);
    });
});
Example #13
0
<?php

DatawrapperVisualization::register($plugin, array('id' => 'bar-chart', 'title' => __('bar chart'), 'version' => '1.3.2', 'extends' => 'raphael-chart', 'order' => 995, 'dimensions' => 1, 'axes' => array('labels' => array('accepts' => array('text', 'date')), 'bars' => array('accepts' => array('number'), 'multiple' => true)), 'options' => array('base-color' => array('type' => 'base-color', 'label' => __('base-color')), 'sort-values' => array('type' => 'checkbox', 'label' => __('sort-bars')), 'reverse-order' => array('type' => 'checkbox', 'label' => __('reverse-order')), 'negative-color' => array('type' => 'checkbox', 'label' => __('negative-values'), 'depends-on' => array('chart.min_value[columns]' => '<0')), 'absolute-scale' => array('type' => 'checkbox', 'label' => __('same-scale')), 'filter-missing-values' => array('type' => 'checkbox', 'default' => true, 'label' => __('filter-missing'))), 'libraries' => array()));
Example #14
0
<?php

DatawrapperVisualization::register($plugin, array('title' => __('Line Chart'), 'id' => 'line-chart', 'extends' => 'raphael-chart', 'dimensions' => 2, 'order' => 40, 'axes' => array('x' => array('accepts' => array('text', 'date')), 'y1' => array('accepts' => array('number'), 'multiple' => true), 'y2' => array('accepts' => array('number'), 'multiple' => true, 'optional' => true)), 'options' => array('base-color' => array('type' => 'base-color', 'label' => __('Base color')), 'sep-labeling' => array('type' => 'separator', 'label' => __('Customize labeling'), 'depends-on' => array('chart.min_columns[y1]' => 2)), 'direct-labeling' => array('type' => 'checkbox', 'label' => __('Direct labeling'), 'default' => false, 'depends-on' => array('chart.min_columns[y1]' => 2, 'chart.max_columns[y2]' => 0), 'help' => __('Show the labels right nearby the line ends instead of a separate legend')), 'legend-position' => array('type' => 'radio-left', 'label' => __('Legend position'), 'default' => 'right', 'depends-on' => array('direct-labeling' => false, 'chart.min_columns[y1]' => 2), 'options' => array(array('value' => 'right', 'label' => __('right')), array('value' => 'top', 'label' => __('top')), array('value' => 'inside', 'label' => __('inside left')), array('value' => 'inside-right', 'label' => __('inside right')))), 'sep-lines' => array('type' => 'separator', 'label' => __('Customize lines')), 'show-grid' => array('type' => 'checkbox', 'hidden' => true, 'label' => __('Show grid'), 'default' => false), 'connect-missing-values' => array('type' => 'checkbox', 'label' => __('Connect lines between missing values')), 'fill-between' => array('type' => 'checkbox', 'label' => __('Fill area between lines'), 'default' => false, 'depends-on' => array('chart.min_columns[y1]' => 2, 'chart.max_columns[y1]' => 2, 'chart.max_columns[y2]' => 0)), 'fill-below' => array('type' => 'checkbox', 'label' => __('Fill area below line'), 'defaut' => false, 'depends-on' => array('chart.min_columns[y1]' => 1, 'chart.max_columns[y1]' => 1, 'chart.max_columns[y2]' => 0)), 'banking' => array('type' => 'linechart-banking', 'label' => __('Suggest aspect ratio that banks average line slopes to 45°'), 'help' => __('Adjust the chart height so that the lines are banked to 45° (on average). Can help to avoid exaggerating and understating of slopes.')), 'line-mode' => array('type' => 'radio-left', 'label' => __('Line interpolation'), 'options' => array(array('label' => __('Straight'), 'value' => 'straight'), array('label' => __('Curved'), 'value' => 'curved'), array('label' => __('Stepped'), 'value' => 'stepped')), 'default' => 'straight'), 'sep-y-axis' => array('type' => 'separator', 'label' => __('Customize y-axis')), 'custom-range-y' => array('type' => 'custom-range', 'label' => __('Custom range'), 'help' => __('This feature allows you to explicitely extend the y axis to custom values. Swap min/max to invert the axis.')), 'scale-y1' => array('type' => 'radio-left', 'label' => __('Scale (y-axis)'), 'options' => array(array('label' => __('linear'), 'value' => 'linear'), array('label' => __('logarithmic'), 'value' => 'log')), 'default' => 'linear', 'depends-on' => array('chart.min_value[y1]' => '>0', 'chart.magnitude_range[y1]' => '>3')), 'user-change-scale' => array('type' => 'checkbox', 'label' => __('Let user change scale'), 'default' => false, 'depends-on' => array('chart.min_value[y1]' => '>0', 'chart.magnitude_range[y1]' => '>3')), 'annotate-time-axis' => array('type' => 'textarea', 'label' => __('Annotate x axis') . ':', 'placeholder' => 'from,to,text', 'width' => '180px')), 'locale' => array('tooManyLinesToLabel' => __('Your chart contains <b>more lines than we can label</b>, so automatic labeling is turned off. To fix this <ul><li>filter some columns in the data table in the previous step, or</li><li>use direct labeling and the highlight feature to label the lines that are important to your story.</li></ul>'), 'useLogarithmicScale' => __('Use logarithmic scale'), 'couldNotParseAllDates' => str_replace('%s', 'http://blog.datawrapper.de/2013/cleaning-your-data-in-datawrapper/', __('Some of the <b>dates in your x-axis could not be parsed</b>, hence the line chart cannot display a proper date axis. To fix this<ul><li>return to the previous step and clean your date column.</li><li><a href="%s">Read more about how to do this.</a></li></ul>')))));
global $app;
DatawrapperHooks::register(DatawrapperHooks::VIS_OPTION_CONTROLS, function ($o, $k) use($app, $plugin) {
    $env = array('option' => $o, 'key' => $k);
    $app->render('plugins/' . $plugin->getName() . '/banking.twig', $env);
});
$plugin->declareAssets(array('banking.js'), "|/chart/[^/]+/visualize|");
Example #15
0
<?php

DatawrapperVisualization::register($plugin, array('id' => 'election-donut-chart', 'title' => __('Election Donut'), 'extends' => 'donut-chart', 'dimensions' => 1, 'order' => 60, 'axes' => array('labels' => array('accepts' => array('text', 'date')), 'slices' => array('accepts' => array('number'), 'multiple' => true)), 'options' => array('base-color' => array('type' => 'base-color', 'label' => __('Base color')), 'sort-values' => array('type' => 'checkbox', 'label' => __('Sort by size'), 'default' => true))));
Example #16
0
 * system and parsing of several JSON files
 *
 * it will be cached once per user session but should be
 * used carefully anyway. never call this in embedded charts
 */
$app->get('/visualizations', function () {
    if (false && isset($_SESSION['dw-visualizations'])) {
        // read from session cache
        // ToDo: use user-independend cache here (e.g. memcache)
        $res = $_SESSION['dw-visualizations'];
    } else {
        // read from file system
        $res = DatawrapperVisualization::all();
        // store in cache
        $_SESSION['dw-visualizations'] = $res;
    }
    ok($res);
});
$app->get('/visualizations/:visid', function ($visid) {
    if (false && isset($_SESSION['dw-visualizations-' . $visid])) {
        // read from session cache
        // ToDo: use user-independend cache here (e.g. memcache)
        $res = $_SESSION['dw-visualizations-' . $visid];
    } else {
        // read from file system
        $res = DatawrapperVisualization::get($visid);
        // store in cache
        $_SESSION['dw-visualizations-' . $visid] = $res;
    }
    ok($res);
});
<?php

require_once '../lib/utils/themes.php';
/*
 * VISUALIZE STEP
 */
$app->get('/chart/:id/visualize', function ($id) use($app) {
    disable_cache($app);
    check_chart_writable($id, function ($user, $chart) use($app) {
        $page = array('chartData' => $chart->loadData(), 'chart' => $chart, 'visualizations' => DatawrapperVisualization::all(), 'vis' => DatawrapperVisualization::get($chart->getType()), 'themes' => DatawrapperTheme::all(), 'theme' => DatawrapperTheme::get($chart->getTheme()), 'debug' => !empty($GLOBALS['dw_config']['debug_export_test_cases']) ? '1' : '0');
        add_header_vars($page, 'chart');
        add_editor_nav($page, 3);
        $app->render('chart-visualize.twig', $page);
    });
});
Example #18
0
 function init()
 {
     DatawrapperVisualization::register($this, $this->getMeta_PieChart());
     DatawrapperVisualization::register($this, $this->getMeta_DonutChart());
 }
Example #19
0
        $page['plain'] = $app->request()->get('plain') == 1;
        $page['fullscreen'] = $app->request()->get('fs') == 1;
        $page['innersvg'] = $app->request()->get('innersvg') == 1;
        if (!empty($GLOBALS['dw_config']['prevent_chart_preview_in_iframes'])) {
            // prevent this url from being rendered in iframes on different
            // domains, mainly to protect server resources
            $res = $app->response();
            $res['X-Frame-Options'] = 'SAMEORIGIN';
        }
        $app->render('chart.twig', $page);
    });
});
$app->get('/chart/:id/nojs.png', function ($id) use($app) {
    $app->redirect('/static/img/nojs.png');
});
// always redirect to url without trailing slash
$app->get('/chart/:id/preview/', function ($id) use($app) {
    $app->redirect("/chart/{$id}/preview");
});
// static route to emulate published vis files
$app->get('/chart/:id/_static/:file+', function ($id, $parts) use($app) {
    check_chart_readable($id, function ($user, $chart) use($app, $parts) {
        $fn = implode('/', $parts);
        $vis = DatawrapperVisualization::get($chart->getType());
        if (file_exists(ROOT_PATH . 'www/' . $vis['__static_path'] . $fn)) {
            $app->redirect($vis['__static_path'] . $fn);
        } else {
            $app->notFound();
        }
    });
});
Example #20
0
    if (!empty($GLOBALS['dw_config']['debug_export_test_cases'])) {
        if_chart_exists($chart_id, function ($chart) use($app) {
            $json = $chart->serialize();
            $payload = json_decode($app->request()->getBody(), true);
            $name = $payload['id'];
            $json['_data'] = $chart->loadData();
            $json['_sig'] = $payload['signature'];
            if (empty($name)) {
                error('', 'no name specified');
            } else {
                $name = str_replace(" ", "-", $name);
                $json['_id'] = $name;
                file_put_contents("../../test/test-charts/" . $name . ".json", json_encode($json));
                ok();
            }
        });
    }
});
$app->get('/charts/:id/vis-data', function ($chart_id) {
    if_chart_is_readable($chart_id, function ($user, $chart) {
        try {
            $allVis = array();
            foreach (DatawrapperVisualization::all() as $vis) {
                $allVis[$vis['id']] = $vis;
            }
            ok(array('visualizations' => $allVis, 'vis' => DatawrapperVisualization::get($chart->getType()), 'themes' => DatawrapperTheme::all()));
        } catch (Exception $e) {
            error('io-error', $e->getMessage());
        }
    });
});
Example #21
0
 public function init()
 {
     DatawrapperVisualization::register($this, $this->getMeta_Simple());
     DatawrapperVisualization::register($this, $this->getMeta_Grouped());
     DatawrapperVisualization::register($this, $this->getMeta_Stacked());
 }
Example #22
0
            $user_csv .= $lbl . ';';
            $user_csv .= isset($data['users_activated'][$key]) ? $data['users_activated'][$key] : '-';
            $user_csv .= ';';
            $user_csv .= isset($data['users_signed'][$key]) ? $data['users_signed'][$key] : '-';
            $user_csv .= "\\n";
            $chart_csv .= $lbl . ';';
            // $chart_csv .= isset($data['charts_uploaded'][$lbl]) ? $data['charts_uploaded'][$lbl] : '-';
            // $chart_csv .= ';';
            // $chart_csv .= isset($data['charts_described'][$lbl]) ? $data['charts_described'][$lbl] : '-';
            // $chart_csv .= ';';
            $chart_csv .= isset($data['charts_visualized'][$key]) ? $data['charts_visualized'][$key] : '-';
            $chart_csv .= ';';
            $chart_csv .= isset($data['charts_published'][$key]) ? $data['charts_published'][$key] : '-';
            $chart_csv .= "\\n";
        }
        $page = array('title' => 'Dashboard', 'user_csv' => $user_csv, 'chart_csv' => $chart_csv, 'linechart' => DatawrapperVisualization::get('line-chart'), 'chartLocale' => 'en-US');
        add_header_vars($page, 'admin');
        add_adminpage_vars($page, '/admin');
        $app->render('admin-dashboard.twig', $page);
    } else {
        $app->notFound();
    }
});
$app->get('/admin/themes/?', function () use($app) {
    $user = DatawrapperSession::getUser();
    if ($user->isAdmin()) {
        $page = array('title' => 'Themes', 'themes' => DatawrapperTheme::all(), 'count' => count_charts_per_themes());
        add_header_vars($page, 'admin');
        add_adminpage_vars($page, '/admin/themes');
        $app->render('admin-themes.twig', $page);
    } else {
Example #23
0
function get_chart_content($chart, $user, $published = false, $debug = false)
{
    if (!function_exists('unique_scripts')) {
        function unique_scripts($scripts)
        {
            $exist = array();
            $out = array();
            foreach ($scripts as $s) {
                $src = is_array($s) ? $s['src'] : $s;
                if (isset($exist[$src])) {
                    continue;
                }
                $exist[$src] = true;
                $out[] = is_array($s) ? $s : array('src' => $s);
            }
            return $out;
        }
    }
    $theme_css = array();
    $theme_js = array();
    $protocol = get_current_protocol();
    $next_theme_id = $chart->getTheme();
    $locale = DatawrapperSession::getLanguage();
    if ($chart->getLanguage() != '') {
        $locale = $chart->getLanguage();
    }
    $static_path = $GLOBALS['dw_config']['static_path'];
    $abs = $protocol . '://' . $GLOBALS['dw_config']['domain'];
    if ($static_path == 'static/') {
        $static_path = $abs . $static_path;
    }
    while (!empty($next_theme_id)) {
        $theme = DatawrapperTheme::get($next_theme_id);
        // $theme_static_path = str_replace('/static/', $static_path . '/', $theme['__static_path']);
        $theme_static_path = $theme['__static_path'];
        $theme_js[] = $theme_static_path . $next_theme_id . '.js';
        if ($theme['hasStyles']) {
            $theme_css[] = $theme_static_path . $next_theme_id . '.css';
        }
        $next_theme_id = $theme['extends'];
    }
    $abs = $protocol . '://' . $GLOBALS['dw_config']['domain'];
    $debug = $GLOBALS['dw_config']['debug'] == true || $debug;
    $culture = str_replace('_', '-', $locale);
    if ($published && !empty($GLOBALS['dw_config']['asset_domain'])) {
        $base_js = array('//' . $GLOBALS['dw_config']['asset_domain'] . '/globalize.min.js', '//' . $GLOBALS['dw_config']['asset_domain'] . '/cultures/globalize.culture.' . $culture . '.js', '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js', '//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.1/jquery.min.js');
    } else {
        // use "local" assets
        $base_js = array($abs . '/static/vendor/globalize/globalize.min.js', $abs . '/static/vendor/globalize/cultures/globalize.culture.' . $culture . '.js', $abs . '/static/vendor/underscore/underscore-min.js', $abs . '/static/vendor/jquery/jquery.min.js');
    }
    $vis_js = array();
    $vis_css = array();
    $next_vis_id = $chart->getType();
    $vis_libs = array();
    $vis_libs_cdn = array();
    $vis_libs_local = array();
    $vis_locale = array();
    // visualizations may define localized strings, e.g. "other"
    while (!empty($next_vis_id)) {
        $vis = DatawrapperVisualization::get($next_vis_id);
        // $vis_static_path = str_replace('/static/', $static_path . '/', $vis['__static_path']);
        $vis_static_path = $vis['__static_path'];
        $vjs = array();
        if (!empty($vis['libraries'])) {
            foreach (array_reverse($vis['libraries']) as $script) {
                if (!is_array($script)) {
                    $script = array("local" => $script, "cdn" => false);
                }
                if (!empty($script['cdn'])) {
                    $script['src'] = $script['cdn'];
                    $vis_libs_cdn[] = $script;
                }
                // at first we check if the library lives in ./lib of the vis module
                if (file_exists(ROOT_PATH . 'www' . $vis['__static_path'] . $script['local'])) {
                    $u = $vis_static_path . $script['local'];
                } else {
                    if (file_exists(ROOT_PATH . 'www/static/vendor/' . $script['local'])) {
                        $u = '/static/vendor/' . $script['local'];
                    } else {
                        print ROOT_PATH . 'www' . $vis['__static_path'] . $script['local'];
                        die("could not find required library " . $script["local"]);
                    }
                }
                $script['src'] = $u;
                $vis_libs[] = $script;
                if (empty($url['cdn'])) {
                    $vis_libs_local[] = $script;
                }
            }
        }
        if (!empty($vis['locale']) && is_array($vis['locale'])) {
            foreach ($vis['locale'] as $term => $translations) {
                if (!isset($vis_locale[$term])) {
                    $vis_locale[$term] = $translations;
                }
            }
        }
        $vjs[] = $vis_static_path . $vis['id'] . '.js';
        $vis_js = array_merge($vis_js, array_reverse($vjs));
        if ($vis['hasCSS']) {
            $vis_css[] = $vis_static_path . $vis['id'] . '.css';
        }
        $next_vis_id = !empty($vis['extends']) ? $vis['extends'] : null;
    }
    $stylesheets = array_merge(array('/static/css/chart.base.css'), $vis_css, array_reverse($theme_css));
    $the_vis = DatawrapperVisualization::get($chart->getType());
    $the_vis['locale'] = $vis_locale;
    $the_theme = DatawrapperTheme::get($chart->getTheme());
    $l10n__domain = $the_theme['__static_path'];
    $the_vis_js = get_vis_js($the_vis, array_merge(array_reverse($vis_js), $vis_libs_local));
    $the_theme_js = get_theme_js($the_theme, array_reverse($theme_js));
    $the_chart_js = get_chart_js();
    if ($published) {
        $scripts = array_merge($base_js, $vis_libs_cdn, array('/lib/' . $the_vis_js[0], '/lib/' . $the_theme_js[0], '/lib/' . $the_chart_js[0]));
        $stylesheets = array($chart->getID() . '.all.css');
        // NOTE: replace `/static/` by `assets/` in the `__static_path` value,
        //       since vis assets are handle by DatawrapperVisualization
        $replace_in = $the_vis['__static_path'];
        $replace_by = 'assets/';
        $replace = '/static/';
        $the_vis['__static_path'] = substr_replace($replace_in, $replace_by, strrpos($replace_in, $replace), strlen($replace));
        // length
        $the_theme['__static_path'] = '';
    } else {
        $scripts = unique_scripts(array_merge($base_js, array($static_path . '/js/dw-2.0' . ($debug ? '' : '.min') . '.js'), array_reverse($theme_js), array_reverse($vis_js), array_reverse($vis_libs), array($static_path . '/js/dw/chart.base.js')));
    }
    $cfg = $GLOBALS['dw_config'];
    $published_urls = DatawrapperHooks::execute(DatawrapperHooks::GET_PUBLISHED_URL, $chart);
    if (empty($published_urls)) {
        $chart_url = $protocol . '://' . $cfg['chart_domain'] . '/' . $chart->getID() . '/';
    } else {
        $chart_url = $published_urls[0];
        // ignore urls except from the first one
    }
    $page = array('chartData' => $chart->loadData(), 'chart' => $chart, 'lang' => strtolower(substr($locale, 0, 2)), 'metricPrefix' => get_metric_prefix($locale), 'l10n__domain' => $l10n__domain, 'origin' => !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '', 'DW_DOMAIN' => $protocol . '://' . $cfg['domain'] . '/', 'DW_CHART_DATA' => $protocol . '://' . $cfg['domain'] . '/chart/' . $chart->getID() . '/data.csv', 'ASSET_PATH' => $published ? '' : $the_theme['__static_path'], 'published' => $published, 'chartUrl' => $chart_url, 'embedCode' => '<iframe src="' . $chart_url . '" frameborder="0" allowtransparency="true" allowfullscreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen width="' . $chart->getMetadata('publish.embed-width') . '" height="' . $chart->getMetadata('publish.embed-height') . '"></iframe>', 'chartUrlFs' => strpos($chart_url, '.html') > 0 ? str_replace('index.html', 'fs.html', $chart_url) : $chart_url . '?fs=1', 'stylesheets' => $stylesheets, 'scripts' => $scripts, 'visualization' => $the_vis, 'theme' => $the_theme, 'chartLocale' => str_replace('_', '-', $locale), 'vis_js' => $the_vis_js, 'theme_js' => $the_theme_js, 'chart_js' => $the_chart_js);
    return $page;
}
Example #24
0
<?php

DatawrapperVisualization::register($plugin, array('id' => 'bar-chart', 'title' => __('Bar Chart'), 'version' => '1.3.2', 'extends' => 'raphael-chart', 'order' => 5, 'dimensions' => 1, 'axes' => array('labels' => array('accepts' => array('text', 'date')), 'bars' => array('accepts' => array('number'), 'multiple' => true)), 'options' => array('base-color' => array('type' => 'base-color', 'label' => __('Base color')), 'sort-values' => array('type' => 'checkbox', 'label' => __('Autmatically sort bars')), 'reverse-order' => array('type' => 'checkbox', 'label' => __('Reverse order')), 'negative-color' => array('type' => 'checkbox', 'label' => __('Use different color for negative values'), 'depends-on' => array('chart.min_value[columns]' => '<0')), 'absolute-scale' => array('type' => 'checkbox', 'label' => __('Use the same scale for all columns')), 'filter-missing-values' => array('type' => 'checkbox', 'default' => true, 'label' => __('Filter missing values'))), 'libraries' => array()));
Example #25
0
<?php

require_once ROOT_PATH . 'lib/utils/themes.php';
require_once ROOT_PATH . 'vendor/jsmin/jsmin.php';
/*
 * PUBLISH STEP - shows progress of publishing action and thumbnail generation
 * forwards to /chart/:id/finish
 */
$app->get('/chart/:id/publish', function ($id) use($app) {
    disable_cache($app);
    check_chart_writable($id, function ($user, $chart) use($app) {
        $cfg = $GLOBALS['dw_config'];
        $page = array('title' => $chart->getID() . ' :: ' . __('Publish'), 'chartData' => $chart->loadData(), 'chart' => $chart, 'visualizations' => DatawrapperVisualization::all(), 'vis' => DatawrapperVisualization::get($chart->getType()), 'chartUrl' => $chart->getPublicUrl(), 'chartUrlLocal' => '/chart/' . $chart->getID() . '/preview', 'themes' => DatawrapperTheme::all(), 'exportStaticImage' => !empty($cfg['phantomjs']), 'chartActions' => DatawrapperHooks::execute(DatawrapperHooks::GET_CHART_ACTIONS, $chart), 'estExportTime' => ceil(JobQuery::create()->estimatedTime('export_image') / 60));
        add_header_vars($page, 'chart', 'chart-editor/publish.css');
        add_editor_nav($page, 4);
        if ($user->isAbleToPublish() && ($chart->getLastEditStep() == 3 || $app->request()->get('republish') == 1)) {
            // actual publish process
            $chart->publish();
            $page['chartUrl'] = $chart->getPublicUrl();
            // generate thumbnails
            $page['publish'] = true;
            $page['republish'] = $app->request()->get('republish') == 1;
        }
        $app->render('chart/publish.twig', $page);
    });
});
Example #26
0
<?php

/*
 * PUBLISH STEP - shows progress of publishing action and thumbnail generation
 */
$app->get('/chart/:id/publish', function ($id) use($app) {
    disable_cache($app);
    check_chart_writable($id, function ($user, $chart) use($app) {
        $cfg = $GLOBALS['dw_config'];
        $chartActions = DatawrapperHooks::execute(DatawrapperHooks::GET_CHART_ACTIONS, $chart);
        // add duplicate action
        $chartActions[] = array('id' => 'duplicate', 'icon' => 'code-fork', 'title' => __('Duplicate this chart'), 'order' => 500);
        // sort actions
        usort($chartActions, function ($a, $b) {
            return (isset($a['order']) ? $a['order'] : 999) - (isset($b['order']) ? $b['order'] : 999);
        });
        $chartW = $chart->getMetadata('publish.embed-width');
        $chartH = $chart->getMetadata('publish.embed-height');
        if (substr($chartW, -1) != '%') {
            $chartW .= 'px';
        }
        if (substr($chartH, -1) != '%') {
            $chartH .= 'px';
        }
        $page = array('title' => $chart->getID() . ' :: ' . __('Publish'), 'chartData' => $chart->loadData(), 'chart' => $chart, 'visualizations' => DatawrapperVisualization::all(), 'vis' => DatawrapperVisualization::get($chart->getType()), 'chartUrl' => $chart->getPublicUrl(), 'chartUrlLocal' => '/chart/' . $chart->getID() . '/preview', 'embedWidth' => $chartW, 'embedHeight' => $chartH, 'themes' => DatawrapperTheme::all(), 'exportStaticImage' => !empty($cfg['phantomjs']), 'chartActions' => $chartActions, 'estExportTime' => ceil(JobQuery::create()->estimatedTime('export') / 60));
        add_header_vars($page, 'chart', 'chart-editor/publish.css');
        add_editor_nav($page, 4);
        $app->render('chart/publish.twig', $page);
    });
});