Compare commits

...

8 Commits

8 changed files with 226 additions and 105 deletions

View File

@ -1,3 +1,7 @@
# SimpleWordsCloud
This site allows to create simple words cloud, without any registrations.
There is nothing stored on the server except the words.
## Database
Database config option is set in the dbconfig.php file,
example is in dbconfig_empty.php.

16
common.php Normal file
View File

@ -0,0 +1,16 @@
<?php
function areWordsSimilar(string $word1, string $word2)
{
$word_sim = similar_text($word1, $word2, $word_perc);
$meta_sim = similar_text(metaphone($word1), metaphone($word2), $meta_perc);
$sndx_sim = similar_text(soundex_fr($word1), soundex_fr($word2), $sndx_perc);
if ($word_perc >= 90 || $meta_perc >= 90 || $sndx_perc >= 90) {
return true;
}
if ($word_perc >= 80 && $meta_perc >= 80 && $sndx_perc >= 80) {
return true;
}
return false;
}

View File

@ -29,9 +29,7 @@ if (empty($_POST)) {
</div>
<?php
} else {
$length = 6;
$token = bin2hex(random_bytes($length));
/*$token = bin2hex(random_bytes(DataBase::CLOUD_CODE_LENGTH));*/
if (isset($_POST['fsize']) && is_numeric($_POST['fsize'])) {
$size = $_POST['fsize'];
} else {
@ -42,20 +40,17 @@ if (empty($_POST)) {
} else {
$text = '';
}
if (isset($_POST['fduration']) && in_array($_POST['fduration'], DataBase::OPTIONS_DURATION)) {
if (isset($_POST['fduration']) && key_exists($_POST['fduration'], DataBase::OPTIONS_DURATION)) {
$duration = $_POST['fduration'];
} else {
$duration = DataBase::DEFAULT_DURATION;
}
$cpt = 0;
while (!$db->createCloud($token, $text, $size, $duration) && $cpt < 10) {
$token = bin2hex(random_bytes($length));
$cpt++;
}
$viewUrl = 'result.php?id=' . $token;
$viewName = 'https://' . $_SERVER['HTTP_HOST'] . '/' . $viewUrl;
$voteUrl = 'index.php?id=' . $token;
$voteName = 'https://' . $_SERVER['HTTP_HOST'] . '/' . $voteUrl;
if ($cloud = $db->createCloud($text, $size, $duration)) {
$viewUrl = 'result.php?id=' . $cloud['code'];
$viewName = 'https://' . $_SERVER['HTTP_HOST'] . '/' . $viewUrl;
$voteUrl = 'index.php?id=' . $cloud['code'];
$voteName = 'https://' . $_SERVER['HTTP_HOST'] . '/' . $voteUrl;
?>
<h2><?php echo L::cloud_links_warning ?></h2>
@ -74,5 +69,10 @@ if (empty($_POST)) {
</div>
</div>
<?php
} else {
?>
<h2><?php echo L::create_errorCode ?></h2>
<?php
}
}
include('templates/footer.php');

232
db.php
View File

@ -1,5 +1,6 @@
<?php
require_once 'soundex_fr.php';
require_once 'common.php';
class DataBase
{
@ -11,35 +12,44 @@ class DataBase
'month' => '+1 month'
);
const DEFAULT_SIZE = 3;
const MAX_SIZE = 9;
const CLOUD_CODE_LENGTH = 6;
private $db;
private $cloud;
public function __construct()
{
$this->init();
}
/**
* Initialize the database
*
* Store the PDO object in $db private class variable
*/
public function init()
{
require_once 'dbconfig.php';
$dsn = 'pgsql:dbname=' . $dbname
. ';host=' . $host
. ';port=' . $port;
$dsn = "$type:dbname=$dbname;host=$host;port=$port";
try {
$this->db = new PDO($dsn, $username, $password);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo $e->getMessage();
return null;
}
}
/**
* Check if the database is initialized or not
* @return boolean True if db is inizialized
*/
public function isInit()
{
return isset($this->db);
}
/**
* Build the database tables, only if not existing
*/
public function buildTables()
{
$stmt = $this->db->prepare("
@ -66,34 +76,38 @@ class DataBase
");
$stmt->execute();
}
public function addWord(string $cloud, string $word)
/**
* Add a word to a cloud
*
* If the cloud is specified, it will be loaded and the word
* will be added.
* If the cloud isn't specified, the already loaded cloud will be used.
* @param string $word Word to add
* @param string|int $cloud Id or code of the cloud
*/
public function addWord(string $word, $cloud = null)
{
if (empty($word)) {
return false;
}
$stmt = $this->db->prepare("
SELECT *
FROM clouds
WHERE code = :id;
");
$stmt->bindValue(':id', $cloud, PDO::PARAM_STR);
$stmt->execute();
$cloudId = null;
if ($data = $stmt->fetch()) {
$cloudId = $data['id_cloud'];
} else {
if (isset($cloud)) {
if (!$this->loadCloud($cloud)) {
return false;
}
}
if (!$this->isCloudSet()) {
return false;
}
$stmt = $this->db->prepare("
SELECT *
FROM words
WHERE cloud_id = :cid;
");
$stmt->bindValue(':cid', $cloudId, PDO::PARAM_INT);
$stmt->bindValue(':cid', $this->cloud['id'], PDO::PARAM_INT);
$stmt->execute();
while($data = $stmt->fetch()) {
if ($this->areWordsSimilar($data['word'], $word)) {
if (areWordsSimilar($data['word'], $word)) {
$word = $data['word'];
$wordId = $data['id_word'];
break;
@ -113,7 +127,7 @@ class DataBase
VALUES (:w, :cid);
");
$stmt->bindValue(':w', $word, PDO::PARAM_STR);
$stmt->bindValue(':cid', $cloudId, PDO::PARAM_INT);
$stmt->bindValue(':cid', $this->cloud['id'], PDO::PARAM_INT);
$stmt->execute();
}
}
@ -149,63 +163,151 @@ class DataBase
array_multisort($values, SORT_DESC, $words);
return $words;
}
public function getWordsPercentage(string $id)
{
$words = $this->getWordsList($id);
$total = 0;
foreach ($words as $word) {
$total += $word[1];
}
foreach ($words as $key => $word) {
$words[$key] = array($word[0], $word[1] / $total);
}
return $words;
}
public function getWordsRelative(string $id)
{
$words = $this->getWordsList($id);
$wordsClean = [];
foreach ($words as $key => $word) {
$wordsClean[] = array($word['word'], $word['relative']);
}
return $wordsClean;
}
/**
* Create a new cloud
*
* The function will try to generate a new code for the cloud,
* if it fails, the function will return false, otherwise the
* cloud local variable will save the new cloud.
* @param string $text Text associated to the cloud.
* @param int $size The number of words asked each time,
* must be between 1 and MAX_SIZE.
* @param string $duration Duration code, from OPTIONS_DURATION.
* @return False if error, the cloud if success
*/
public function createCloud(
string $ref,
string $text = '',
int $size = null,
int $size = null,
string $duration = null)
{
if (!isset($size)) {
$size = 3;
} elseif ($size < 1) {
$size = 1;
} elseif ($size > self::MAX_SIZE) {
$size = self::MAX_SIZE;
}
if (!isset($duration)) {
$duration = self::DEFAULT_DURATION;
} elseif (!in_array($duration, self::OPTIONS_DURATION)) {
} elseif (!key_exists($duration, self::OPTIONS_DURATION)) {
$duration = self::DEFAULT_DURATION;
}
$duration = date('Y-m-d H:i:s', strtotime($duration));
$cpt = 0;
$codeIsUsed = true;
while ($codeIsUsed && $cpt < 0) {
$code = bin2hex(random_bytes(self::CLOUD_CODE_LENGTH));
$stmt = $this->db->prepare("
SELECT *
FROM clouds
WHERE code = :code;
");
$stmt->bindValue(':code', $code);
$stmt->execute();
if (!$data = $stmt->fetch()) {
$codeIsUsed = false;
}
$cpt++;
}
if ($codeIsUsed) {
return false;
}
$duration = date('Y-m-d H:i:s', strtotime(self::OPTIONS_DURATION[$duration]));
$stmt = $this->db->prepare("
INSERT INTO clouds(code, text, size, delete_t)
VALUES (:code, :text, :size, :duration);
");
$stmt->bindValue(':code', $ref);
$stmt->bindValue(':text', $text);
$stmt->bindValue(':size', $size);
$stmt->bindValue(':code', $code, PDO::PARAM_STR);
$stmt->bindValue(':text', $text, PDO::PARAM_STR);
$stmt->bindValue(':size', $size, PDO::PARAM_INT);
$stmt->bindValue(':duration', $duration, PDO::PARAM_STR);
try {
$stmt->execute();
} catch (PDOEXception $e) {
return false;
}
return true;
$this->cloud = array(
'id' => $this->db->lastInsertId(),
'code' => $code,
'size' => $size,
'delete_t' => $duration,
'text' => $text,
);
return $this->cloud;
}
public function loadCloud($ref)
{
if (is_int($ref)) {
return $this->loadCloudById($ref);
} elseif (is_string($ref)) {
return $this->loadCloudByCode($ref);
}
}
/**
* Load the cloud by its id
* @param int $id code of the cloud
* @return boolean True if the loading is done, False otherwise
*/
public function loadCloudById(int $id)
{
$stmt = $this->db->prepare("
SELECT *
FROM clouds
WHERE id_cloud = :id;
");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->execute();
if ($data = $stmt->fetch()) {
$this->cloud = array(
'id' => $data['id_cloud'],
'code' => $data['code'],
'size' => $data['size'],
'delete_t' => $data['delete_t'],
'text' => $data['text'],
);
return true;
}
$this->cloud = null;
return false;
}
/**
* Load the cloud by its code
* @param string $code code of the cloud
* @return boolean True if the loading is done, False otherwise
*/
public function loadCloudByCode(string $code)
{
$stmt = $this->db->prepare("
SELECT *
FROM clouds
WHERE code = :code;
");
$stmt->bindValue(':code', $code, PDO::PARAM_STR);
$stmt->execute();
if ($data = $stmt->fetch()) {
$this->cloud = array(
'id' => $data['id_cloud'],
'code' => $data['code'],
'size' => $data['size'],
'delete_t' => $data['delete_t'],
'text' => $data['text'],
);
return true;
}
$this->cloud = null;
return false;
}
public function isCloudSet()
{
return isset($this->cloud);
}
public function getCloudId()
{
if ($this->isCloudSet()) {
return $this->cloud['id'];
}
return null;
}
public function getCloudSize(string $ref)
{
$stmt = $this->db->prepare("
@ -278,18 +380,4 @@ class DataBase
}
return false;
}
function areWordsSimilar(string $word1, string $word2)
{
$word_sim = similar_text($word1, $word2, $word_perc);
$meta_sim = similar_text(metaphone($word1), metaphone($word2), $meta_perc);
$sndx_sim = similar_text(soundex_fr($word1), soundex_fr($word2), $sndx_perc);
if ($word_perc >= 90 || $meta_perc >= 90 || $sndx_perc >= 90) {
return true;
}
if ($word_perc >= 80 && $meta_perc >= 80 && $sndx_perc >= 80) {
return true;
}
return false;
}
}

View File

@ -1,5 +1,5 @@
<?php
$type = 'pgsql';
$host = 'localhost';
$dbname = '';
$username = '';

View File

@ -12,8 +12,12 @@ if (!isset($_GET['id'])) {
}
$id = $_GET['id'];
if ($words = $db->getWordsRelative($id)) {
echo json_encode($words);
if ($words = $db->getWordsList($id)) {
$wordsClean = [];
foreach ($words as $key => $word) {
$wordsClean[] = array($word['word'], $word['relative']);
}
echo json_encode($wordsClean);
} else {
echo json_encode('No id');
}

View File

@ -42,6 +42,11 @@ message = "Vous pouvez entrer ici un ou plusieurs mots, les mots vides ne seront
submit = "Enregistrer"
word = "Mot %d"
success = "Vos mots ont bien été enregistrés, merci de votre participation."
missingId = "Le formulaire est mal formé, veuillez contacter la personne responsable du site."
cloudNotFound = "Le nuage <em>%s</em> n'a pas été trouvé, veuillez vérifier votre lien."
[create]
errorCode = "Erreur lors de la création du nuage, désolé du dérangement."
[duration]
day = "un jour"

View File

@ -7,24 +7,28 @@ if (empty($_POST)) {
}
include 'templates/header.php';
$id = null;
$cpt = 0;
$already_used = array();
foreach ($_POST as $name => $value) {
$cpt;
if ($name == 'fid') {
$id = $value;
continue;
}
if (isset($id) && !in_array($value, $already_used)) {
$already_used[] = $value;
$value = trim(strtolower($value));
$db->addWord($id, $value);
}
if ($cpt > 9) {
break;
if (!isset($_POST['fid'])) {
echo sprintf('<h3>%s</h3>', L::save_missingId);
} elseif (!$db->loadCloud($_POST['fid'])) {
echo sprintf('<h3>%s</h3>', L::save_cloudNotFound($_POST['fid']));
} else {
$cpt = 0;
$already_used = array();
foreach ($_POST as $name => $value) {
if ($name == 'fid') {
continue;
}
$cpt++;
if (!in_array($value, $already_used)) {
$already_used[] = $value;
$value = trim(strtolower($value));
$db->addWord($value);
}
if ($cpt > 9) {
break;
}
}
echo sprintf('<h3>%s</h3>', L::save_success);
}
echo sprintf('<h3>%s</h3>', L::save_success);
include 'templates/footer.php';