Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
WordCloud
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 7
342
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 addWord
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getCloudSize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCloudHtml
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
30
 defaultTextCallback
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 shuffleCloud
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 getClassFromPercent
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace MediaWiki\Extension\CodeReview\UI;
4
5use Html;
6
7/**
8 * wordCloud Copyright 2007 Derek Harvey
9 * www.lotsofcode.com
10 *
11 * This file is part of wordCloud.
12 *
13 * wordCloud is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * wordCloud is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with wordCloud; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * ---
28 * Adapted for use with MediaWiki, cleaned up coding style, etc on 2010-11-03
29 */
30class WordCloud {
31    /**
32     * Nice big array of words and their weights
33     * @var array
34     */
35    private $wordsArray = [];
36
37    /**
38     * An optional callback to format the text before outputting
39     * @var callback
40     */
41    private $callback;
42
43    /**
44     * Mapping of percentage limits to their CSS classes
45     * @var array
46     */
47    private $classPercentages = [
48        1 => 99, 2 => 70, 3 => 60,
49        4 => 50, 5 => 40, 6 => 30,
50        7 => 20, 8 => 10, 9 => 5
51    ];
52
53    /**
54     * Constructor
55     *
56     * @param array $words Array of word => rank pairs
57     * @param Callback|null $callback
58     */
59    public function __construct( array $words = [], $callback = null ) {
60        foreach ( $words as $word => $rank ) {
61            $this->addWord( $word, $rank );
62        }
63        $this->callback = $callback ?: [ $this, 'defaultTextCallback' ];
64    }
65
66    /**
67     * Assign word to array
68     *
69     * @param string $word The word to add
70     * @param int $value The weight to give it
71     */
72    public function addWord( $word, $value = 1 ) {
73        $word = strtolower( $word );
74        if ( array_key_exists( $word, $this->wordsArray ) ) {
75            $this->wordsArray[$word] += $value;
76        } else {
77            $this->wordsArray[$word] = $value;
78        }
79    }
80
81    /**
82     * Calculate size of words array
83     *
84     * @return int
85     */
86    public function getCloudSize() {
87        return array_sum( $this->wordsArray );
88    }
89
90    /**
91     * Create the HTML code for each word and apply font size.
92     *
93     * @return string
94     */
95    public function getCloudHtml() {
96        global $wgCodeReviewShuffleTagCloud;
97        if ( count( $this->wordsArray ) === 0 ) {
98            return '';
99        }
100
101        if ( $wgCodeReviewShuffleTagCloud ) {
102            $this->shuffleCloud();
103        } else {
104            ksort( $this->wordsArray );
105        }
106
107        $max = max( $this->wordsArray );
108        if ( is_array( $this->wordsArray ) ) {
109            $return = '';
110            foreach ( $this->wordsArray as $word => $popularity ) {
111                $sizeRange = $this->getClassFromPercent( ( $popularity / $max ) * 100 );
112                $return .= call_user_func_array( $this->callback, [ $word, $sizeRange ] );
113            }
114            return '<div class="mw-wordcloud">' . $return . '</div>';
115        }
116        return '';
117    }
118
119    /**
120     * Default text callback for word display
121     *
122     * @param string $word
123     * @param string $sizeRange
124     * @return string
125     */
126    public function defaultTextCallback( $word, $sizeRange ) {
127        return Html::element( 'span', [
128            'class' => 'mw-wordcloud-size-' . $sizeRange ], $word );
129    }
130
131    /**
132     * Shuffle associated names in array
133     */
134    private function shuffleCloud() {
135        $keys = array_keys( $this->wordsArray );
136
137        shuffle( $keys );
138
139        if ( count( $keys ) ) {
140            $tmpArray = $this->wordsArray;
141            $this->wordsArray = [];
142            foreach ( $keys as $value ) {
143                $this->wordsArray[$value] = $tmpArray[$value];
144            }
145        }
146    }
147
148    /**
149     * Get the class range using a percentage
150     *
151     * @param int $percent
152     * @return int
153     */
154    private function getClassFromPercent( $percent ) {
155        foreach ( $this->classPercentages as $class => $limit ) {
156            if ( $percent >= $limit ) {
157                return $class;
158            }
159        }
160        return max( array_keys( $this->classPercentages ) ) + 1;
161    }
162}