[dev] [commit] r925 - patches phplib/models templates/struct wwwbase/js wwwbase/struct

automailer at dexonline.ro automailer at dexonline.ro
Mon Aug 12 17:11:46 EEST 2013


Author: cata
Date: Mon Aug 12 17:11:45 2013
New Revision: 925

Log:
Add proper validation to the meaning editor. Now when the validation fails,
the information correctly propagates across requests.

Added:
   patches/00090.sql
Modified:
   phplib/models/BaseObject.php
   phplib/models/Lexem.php
   phplib/models/Meaning.php
   templates/struct/dexEdit.ihtml
   templates/struct/index.ihtml
   wwwbase/js/struct.js
   wwwbase/struct/dexEdit.php
   wwwbase/struct/index.php

Added: patches/00090.sql
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ patches/00090.sql	Mon Aug 12 17:11:45 2013	(r925)
@@ -0,0 +1,2 @@
+alter table Lexem change pronounciations pronunciations varchar(255);
+alter table Lexem change variantOf variantOfId int;

Modified: phplib/models/BaseObject.php
==============================================================================
--- phplib/models/BaseObject.php	Fri Aug  9 19:04:33 2013	(r924)
+++ phplib/models/BaseObject.php	Mon Aug 12 17:11:45 2013	(r925)
@@ -16,6 +16,15 @@
     die("BaseObject::__callStatic() cannot handle method '$name'");
   }
 
+  /* Loads a collection of objects with the given ids, preserving the order. */
+  static function loadByIds($ids) {
+    $results = array();
+    foreach ($ids as $id) {
+      $results[] = Model::factory(get_called_class())->where('id', $id)->find_one();
+    }
+    return $results;
+  }
+
   function save() {
     /* Auto-save the createDate and modDate fields if the model has them */
     if ($this instanceof DatedObject) {

Modified: phplib/models/Lexem.php
==============================================================================
--- phplib/models/Lexem.php	Fri Aug  9 19:04:33 2013	(r924)
+++ phplib/models/Lexem.php	Mon Aug 12 17:11:45 2013	(r925)
@@ -148,7 +148,7 @@
   }
 
   public function getVariantIds() {
-    $variants = Model::factory('Lexem')->select('id')->where('variantOf', $this->id)->find_many();
+    $variants = Model::factory('Lexem')->select('id')->where('variantOfId', $this->id)->find_many();
     $ids = array();
     foreach ($variants as $variant) {
       $ids[] = $variant->id;
@@ -329,13 +329,13 @@
         $errorCount++;
       }
       // (2) they are not already variants of another lexem
-      if ($variant->variantOf && $variant->variantOf != $this->id) {
-        $other = Lexem::get_by_id($variant->variantOf);
+      if ($variant->variantOfId && $variant->variantOfId != $this->id) {
+        $other = Lexem::get_by_id($variant->variantOfId);
         FlashMessage::add("\"{$variant}\" este deja marcat ca variantă a lui \"{$other}\".");
         $errorCount++;
       }
       // (3) they do not have their own variants and
-      $variantVariantCount = Model::factory('Lexem')->where('variantOf', $variant->id)->count();
+      $variantVariantCount = Model::factory('Lexem')->where('variantOfId', $variant->id)->count();
       if ($variantVariantCount) {
         FlashMessage::add("\"{$variant}\" are deja propriile lui variante.");
         $errorCount++;
@@ -348,19 +348,19 @@
       }
     
       if (!$errorCount) {
-        $variant->variantOf = $this->id;
+        $variant->variantOfId = $this->id;
         $variant->save();
       }
     }
 
     // Delete variants no longer in the list
     if ($variantIds) {
-      $lexemsToClear = Model::factory('Lexem')->where('variantOf', $this->id)->where_not_in('id', $variantIds)->find_many();
+      $lexemsToClear = Model::factory('Lexem')->where('variantOfId', $this->id)->where_not_in('id', $variantIds)->find_many();
     } else {
-      $lexemsToClear = Lexem::get_all_by_variantOf($this->id);
+      $lexemsToClear = Lexem::get_all_by_variantOfId($this->id);
     }
     foreach($lexemsToClear as $l) {
-      $l->variantOf = null;
+      $l->variantOfId = null;
       $l->save();
     }
   }
@@ -430,10 +430,10 @@
       InflectedForm::deleteByLexemId($this->id);
       Meaning::deleteByLexemId($this->id);
     }
-    // Clear the variantOf field for lexems having $this as main.
-    $lexemsToClear = Lexem::get_all_by_variantOf($this->id);
+    // Clear the variantOfId field for lexems having $this as main.
+    $lexemsToClear = Lexem::get_all_by_variantOfId($this->id);
     foreach ($lexemsToClear as $l) {
-      $l->variantOf = null;
+      $l->variantOfId = null;
       $l->save();
     }
     parent::delete();

Modified: phplib/models/Meaning.php
==============================================================================
--- phplib/models/Meaning.php	Fri Aug  9 19:04:33 2013	(r924)
+++ phplib/models/Meaning.php	Mon Aug 12 17:11:45 2013	(r925)
@@ -33,9 +33,11 @@
     return $results;
   }
 
-  /** Returns a dictionary containing:
+  /**
+   * Returns a dictionary containing:
    * 'meaning': a Meaning object
-   * 'children': a recusrive dictionary containing this meaning's children
+   * 'sources', 'tags', 'synonyms', 'antonyms': collections of objects related to the meaning
+   * 'children': a recursive dictionary containing this meaning's children
    **/
   private static function buildTree(&$map, $meaningId, &$children) {
     $results = array('meaning' => $map[$meaningId],
@@ -49,6 +51,39 @@
     }
     return $results;
   }
+
+  /**
+   * Convert a tree produced by the tree editor to the format used by loadTree.
+   * We need this in case validation fails and we cannot save the tree, so we need to display it again.
+   **/
+  static function convertTree($meanings) {
+    $meaningStack = array();
+    $results = array();
+    foreach ($meanings as $tuple) {
+      $row = array();
+      $m = $tuple->id ? self::get_by_id($tuple->id) : Model::factory('Meaning')->create();
+      $m->internalRep = $tuple->internalRep;
+      $m->htmlRep = AdminStringUtil::htmlize($m->internalRep, 0);
+      $m->internalComment = $tuple->internalComment;
+      $m->htmlComment = AdminStringUtil::htmlize($m->internalComment, 0);
+      $row['meaning'] = $m;
+
+      $row['sources'] = Source::loadByIds(StringUtil::explode(',', $tuple->sourceIds));
+      $row['tags'] = MeaningTag::loadByIds(StringUtil::explode(',', $tuple->meaningTagIds));
+      $row['synonyms'] = Lexem::loadByIds(StringUtil::explode(',', $tuple->synonymIds));
+      $row['antonyms'] = Lexem::loadByIds(StringUtil::explode(',', $tuple->antonymIds));
+      $row['children'] = array();
+
+      if ($tuple->level) {
+        $meaningStack[$tuple->level - 1]['children'][] = &$row;
+      } else {
+        $results[] = &$row;
+      }
+      $meaningStack[$tuple->level] = &$row;
+      unset($row);
+    }
+    return $results;
+  }
 
   /* Save a tree produced by the tree editor in dexEdit.php */
   static function saveTree($meanings, $lexem) {

Modified: templates/struct/dexEdit.ihtml
==============================================================================
--- templates/struct/dexEdit.ihtml	Fri Aug  9 19:04:33 2013	(r924)
+++ templates/struct/dexEdit.ihtml	Mon Aug 12 17:11:45 2013	(r925)
@@ -30,7 +30,10 @@
       
       <div id="saveButtonContainer">
         <input id="dexEditSaveButton" type="button" value="salvează totul"/>
-        <div><a href="{$wwwRoot}admin/lexemEdit.php?lexemId={$lexem->id}">editează lexemul</a></div>
+        <div>
+          <a href="?lexemId={$lexem->id}">anulează</a> |
+          <a href="{$wwwRoot}admin/lexemEdit.php?lexemId={$lexem->id}">editează lexemul</a>
+        </div>
       </div>
 
       <div id="parameters" class="box">
@@ -42,91 +45,85 @@
                 title="una sau mai multe silabisiri, despărțite prin virgule"> </span>
           <br/>
 
-          <label for="pronounciations">pronunții:</label>
-          <input id="pronounciations" name="pronounciations" type="text" value="{$lexem->pronounciations}" size="25"/>
+          <label for="pronunciations">pronunții:</label>
+          <input id="pronunciations" name="pronunciations" type="text" value="{$lexem->pronunciations}" size="25"/>
           <span class="tooltip"
                 title="una sau mai multe pronunții, despărțite prin virgule"> </span>
           <br/>
 
-          {if $variantOf}
-            <label>variantă a lui:</label>
-            <a href="dexEdit.php?lexemId={$variantOf->id}">{$variantOf}</a>
-            <span class="tooltip"
-                  title="Acest lexem este variantă a altuia și nu poate avea sensuri, exemple sau etimologii proprii."> </span>
-          {else}
-            <label for="variantIds">variante:</label>
-            <input id="variantIds" name="variantIds" value="{','|implode:$variantIds}" type="text"/>
-            <span class="tooltip"
-                  title="Variantele nu pot avea sensuri, exemple sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
-            <br/>
-          {/if}
+          <label>variantă a lui:</label>
+          <input id="variantOfId" name="variantOfId" value="{$lexem->variantOfId}" type="text"/>
+          <span class="tooltip"
+                title="Variantele nu pot avea sensuri, exemple, variante sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
+          <br/>
+
+          <label for="variantIds">variante:</label>
+          <input id="variantIds" name="variantIds" value="{','|implode:$variantIds}" type="text"/>
+          <span class="tooltip"
+                title="Variantele nu pot avea sensuri, exemple, variante sau etimologii proprii. Ele pot avea pronunții și silabisiri proprii."> </span>
         </div>
       </div>
       <div style="clear: both"></div>
 
-      {if !$variantOf}
-        <div class="box">
-          <div class="boxTitle">Sensuri pentru {include file="common/bits/lexemName.ihtml"}</div>
-          <div id="meaningTreeContainer" class="boxContents">
-            {include file="common/bits/meaningTree.ihtml" meanings=$meanings id="meaningTree"}
-        
-            <div id="meaningMenu">
-              <input type="button" id="addMeaningButton" value="adaugă sens"/>
-              <input type="button" id="addSubmeaningButton" value="adaugă subsens"/>
-              <input type="button" id="deleteMeaningButton" value="șterge sens"/>
-            </div>
+      <div class="box">
+        <div class="boxTitle">Sensuri pentru {include file="common/bits/lexemName.ihtml"}</div>
+        <div id="meaningTreeContainer" class="boxContents">
+          {include file="common/bits/meaningTree.ihtml" meanings=$meanings id="meaningTree"}
+
+          <div id="meaningMenu">
+            <input type="button" id="addMeaningButton" value="adaugă sens"/>
+            <input type="button" id="addSubmeaningButton" value="adaugă subsens"/>
+            <input type="button" id="deleteMeaningButton" value="șterge sens"/>
           </div>
         </div>
-      {/if}
+      </div>
+
+      <div id="dexEditLeftColumn">
+        <div id="meaningEditor" class="box">
+          <div class="boxTitle">Editorul de sensuri</div>
+          <div class="boxContents">
+            <textarea id="editorInternalRep" rows="10" cols="10" disabled="disabled" placeholder="sensul definiției..."></textarea><br/>
+            <textarea id="editorInternalComment" rows="3" cols="10" disabled="disabled" placeholder="comentariu..."></textarea><br/>
 
-      {if !$variantOf}
-        <div id="dexEditLeftColumn">
-          <div id="meaningEditor" class="box">
-            <div class="boxTitle">Editorul de sensuri</div>
-            <div class="boxContents">
-              <textarea id="editorInternalRep" rows="10" cols="10" disabled="disabled" placeholder="sensul definiției..."></textarea><br/>
-              <textarea id="editorInternalComment" rows="3" cols="10" disabled="disabled" placeholder="comentariu..."></textarea><br/>
-        
-              <div class="editorLabel">surse:</div>
-              <div class="editorFieldContainer">
-                <select id="editorSources" multiple="multiple">
-                  {foreach from=$sources item=s}
-                    <option value="{$s->id}">{$s->shortName}</option>
-                  {/foreach}
-                </select>
-              </div>
-              <div style="clear: both"></div>
-        
-              <div class="editorLabel">etichete:</div>
-              <div class="editorFieldContainer">
-                <select id="editorTags" multiple="multiple">
-                  {foreach from=$meaningTags item=mt}
-                    <option value="{$mt->id}">{$mt->value}</option>
-                  {/foreach}
-                </select>
-              </div>
-              <div style="clear: both"></div>
-        
-              <div class="editorLabel">sinonime:</div>
-              <div class="editorFieldContainer">
-                <input id="editorSynonyms" type="hidden"/>
-              </div>
-              <div style="clear: both"></div>
-        
-              <div class="editorLabel">antonime:</div>
-              <div class="editorFieldContainer">
-                <input id="editorAntonyms" type="hidden"/>
-              </div>
-              <div style="clear: both"></div>
-        
-              <input id="editMeaningAcceptButton" type="button" disabled="disabled" value="acceptă"/>
-              <input id="editMeaningCancelButton" type="button" disabled="disabled" value="renunță"/>
+            <div class="editorLabel">surse:</div>
+            <div class="editorFieldContainer">
+              <select id="editorSources" multiple="multiple">
+                {foreach from=$sources item=s}
+                  <option value="{$s->id}">{$s->shortName}</option>
+                {/foreach}
+              </select>
             </div>
+            <div style="clear: both"></div>
+
+            <div class="editorLabel">etichete:</div>
+            <div class="editorFieldContainer">
+              <select id="editorTags" multiple="multiple">
+                {foreach from=$meaningTags item=mt}
+                  <option value="{$mt->id}">{$mt->value}</option>
+                {/foreach}
+              </select>
+            </div>
+            <div style="clear: both"></div>
+      
+            <div class="editorLabel">sinonime:</div>
+            <div class="editorFieldContainer">
+              <input id="editorSynonyms" type="hidden"/>
+            </div>
+            <div style="clear: both"></div>
+      
+            <div class="editorLabel">antonime:</div>
+            <div class="editorFieldContainer">
+              <input id="editorAntonyms" type="hidden"/>
+            </div>
+            <div style="clear: both"></div>
+      
+            <input id="editMeaningAcceptButton" type="button" disabled="disabled" value="acceptă"/>
+            <input id="editMeaningCancelButton" type="button" disabled="disabled" value="renunță"/>
           </div>
         </div>
-      {/if}
+      </div>
       
-      <div id="definitionBox" class="{if !$variantOf}dexEditRightColumn{/if} box">
+      <div id="definitionBox" class="dexEditRightColumn box">
         <div class="boxTitle">Definiții pentru {include file="common/bits/lexemName.ihtml"}</div>
         <div class="boxContents">
           {foreach from=$searchResults item=row}

Modified: templates/struct/index.ihtml
==============================================================================
--- templates/struct/index.ihtml	Fri Aug  9 19:04:33 2013	(r924)
+++ templates/struct/index.ihtml	Mon Aug 12 17:11:45 2013	(r925)
@@ -1,6 +1,6 @@
 <h3>Alege un cuvânt pentru structurare</h3>
 
-<form id="meaningForm" action="dexEdit.php" method="post">
+<form id="meaningForm" action="dexEdit.php" method="get">
 
   <ul>
     <li>
@@ -12,7 +12,7 @@
     <li>
       la alegere:
       <input id="structLexemFinder" type="text" name="lexemId"/>
-      <input type="submit" name="submitButton" value="Caută"/>
+      <button type="button" onclick="$('#meaningForm').submit();">Caută</button>
     </li>
   </ul>
 

Modified: wwwbase/js/struct.js
==============================================================================
--- wwwbase/js/struct.js	Fri Aug  9 19:04:33 2013	(r924)
+++ wwwbase/js/struct.js	Mon Aug 12 17:11:45 2013	(r925)
@@ -23,13 +23,13 @@
     placeholder: 'adaugă o sursă...',
     width: '315px',
   });
-  $('#editorSources').select2('disable');
+  $('#editorSources').select2('enable', false);
 
   $('#editorTags').select2({
     placeholder: 'adaugă o etichetă...',
     width: '315px',
   });
-  $('#editorTags').select2('disable');
+  $('#editorTags').select2('enable', false);
 
   $('#editorSynonyms').select2({
     ajax: struct_lexemAjax,
@@ -39,7 +39,7 @@
     placeholder: 'adaugă un sinonim...',
     width: '315px',
   });
-  $('#editorSynonyms').select2('disable');
+  $('#editorSynonyms').select2('enable', false);
 
   $('#editorAntonyms').select2({
     ajax: struct_lexemAjax,
@@ -49,7 +49,7 @@
     placeholder: 'adaugă un antonim...',
     width: '315px',
   });
-  $('#editorAntonyms').select2('disable');
+  $('#editorAntonyms').select2('enable', false);
 
   $('#editorInternalRep, #editorInternalComment, #editorSources, #editorTags, #editorSynonyms, #editorAntonyms').bind(
     'change keyup input paste', function() { struct_anyChanges = true; });
@@ -62,6 +62,15 @@
     width: '217px',
   });
 
+  $('#variantOfId').select2({
+    ajax: struct_lexemAjax,
+    allowClear: true,
+    initSelection: select2InitSelectionAjaxSingle,
+    minimumInputLength: 1,
+    placeholder: 'alegeți un lexem (opțional)',
+    width: '217px',
+  });
+
   $('#editMeaningAcceptButton').click(acceptMeaningEdit);
   $('#editMeaningCancelButton').click(endMeaningEdit);
   $('#dexEditSaveButton').click(dexEditSaveEverything);
@@ -77,6 +86,7 @@
     ajax: struct_lexemAjax,
     minimumInputLength: 1,
     placeholder: 'caută un lexem...',
+    width: '300px',
   });
 }
 
@@ -142,6 +152,16 @@
   callback(data);
 }
 
+function select2InitSelectionAjaxSingle(element, callback) {
+  var id = $(element).val();
+  if (id) {
+    $.ajax(wwwRoot + 'ajax/getLexemById.php?id=' + id, {dataType: 'json'})
+      .done(function(data) {
+        callback({ id: id, text: data });
+      });
+  }
+}
+
 function select2InitSelectionAjax(element, callback) {
   var data = [];
 
@@ -309,13 +329,13 @@
   $('#editorInternalRep').val('');
   $('#editorInternalComment').val('');
   $('#editorSources').select2('val', []);
-  $('#editorSources').select2('disable');
+  $('#editorSources').select2('enable', false);
   $('#editorTags').select2('val', []);
-  $('#editorTags').select2('disable');
+  $('#editorTags').select2('enable', false);
   $('#editorSynonyms').select2('data', []);
-  $('#editorSynonyms').select2('disable');
+  $('#editorSynonyms').select2('enable', false);
   $('#editorAntonyms').select2('data', []);
-  $('#editorAntonyms').select2('disable');
+  $('#editorAntonyms').select2('enable', false);
 }
 
 // Iterate a meaning tree node recursively and collect meaning-related fields

Modified: wwwbase/struct/dexEdit.php
==============================================================================
--- wwwbase/struct/dexEdit.php	Fri Aug  9 19:04:33 2013	(r924)
+++ wwwbase/struct/dexEdit.php	Mon Aug 12 17:11:45 2013	(r925)
@@ -1,39 +1,39 @@
-<?php
+<?Php
 require_once("../../phplib/util.php"); 
 util_assertModerator(PRIV_EDIT);
 util_assertNotMirror();
 
 $lexemId = util_getRequestIntParameter('lexemId');
 $hyphenations = util_getRequestParameter('hyphenations');
-$pronounciations = util_getRequestParameter('pronounciations');
-$variantIds = util_getRequestParameter('variantIds');
+$pronunciations = util_getRequestParameter('pronunciations');
+$variantIds = util_getRequestCsv('variantIds');
+$variantOfId = util_getRequestParameter('variantOfId');
 $jsonMeanings = util_getRequestParameter('jsonMeanings');
 
 $lexem = Lexem::get_by_id($lexemId);
-$mainVariant = Lexem::get_by_id($lexem->variantOf);
 
 if ($jsonMeanings) {
-  $meanings = json_decode($jsonMeanings);
-  if ($mainVariant && !empty($meanings)) {
-    FlashMessage::add("Acest lexem este o variantă a lui {$mainVariant} și nu poate avea el însuși sensuri.");
-  } else {
-    Meaning::saveTree($meanings, $lexem);
-  }
-
   $lexem->hyphenations = $hyphenations;
-  $lexem->pronounciations = $pronounciations;
-  $lexem->save();
+  $lexem->pronunciations = $pronunciations;
+  $lexem->variantOfId = $variantOfId ? $variantOfId : null;
+  $variantOf = Lexem::get_by_id($lexem->variantOfId);
+  $meanings = json_decode($jsonMeanings);
 
-  // TODO: Add a validation routine that checks everything before saving anything
-  // Save variants, but only if they meet certain criteria
-  $variantIds = StringUtil::explode(',', $variantIds);
-  if ($mainVariant && !empty($variantIds)) {
-    FlashMessage::add("Acest lexem este o variantă a lui {$mainVariant} și nu poate avea el însuși variante.");
-  } else {
+  if (validate($lexem, $variantOf, $variantIds, $meanings)) {
+    // Case 1: Validation passed
+    Meaning::saveTree($meanings, $lexem);
+    $lexem->save();
     $lexem->updateVariants($variantIds);
+    util_redirect("dexEdit.php?lexemId={$lexem->id}");
+  } else {
+    // Case 2: Validation failed
+    SmartyWrap::assign('variantIds', $variantIds);
+    SmartyWrap::assign('meanings', Meaning::convertTree($meanings));
   }
-
-  util_redirect("dexEdit.php?lexemId={$lexem->id}");
+} else {
+  // Case 3: First time loading this page
+  SmartyWrap::assign('variantIds', $lexem->getVariantIds());
+  SmartyWrap::assign('meanings', Meaning::loadTree($lexem->id));
 }
 
 $defs = Definition::loadByLexemId($lexem->id);
@@ -44,14 +44,23 @@
 $meaningTags = Model::factory('MeaningTag')->order_by_asc('value')->find_many();
 
 SmartyWrap::assign('lexem', $lexem);
-SmartyWrap::assign('meanings', Meaning::loadTree($lexem->id));
 SmartyWrap::assign('meaningTags', $meaningTags);
 SmartyWrap::assign('searchResults', $searchResults);
-SmartyWrap::assign('variantOf', $mainVariant);
-SmartyWrap::assign('variantIds', $lexem->getVariantIds());
 SmartyWrap::assign('pageTitle', "Editare lexem: {$lexem->formNoAccent}");
 SmartyWrap::addCss('jqueryui', 'easyui', 'select2', 'struct', 'flex');
 SmartyWrap::addJs('dex', 'jquery', 'easyui', 'jqueryui', 'select2', 'struct');
 SmartyWrap::displayWithoutSkin('struct/dexEdit.ihtml');
 
+/**************************************************************************/
+
+function validate($lexem, $variantOf, $variantIds, $meanings) {
+  if ($variantOf && !empty($meanings)) {
+    FlashMessage::add("Acest lexem este o variantă a lui {$variantOf} și nu poate avea el însuși sensuri.");
+  }
+  if ($variantOf && !empty($variantIds)) {
+    FlashMessage::add("Acest lexem este o variantă a lui {$variantOf} și nu poate avea el însuși variante.");
+  }
+  return FlashMessage::getMessage() == null;
+}
+
 ?>

Modified: wwwbase/struct/index.php
==============================================================================
--- wwwbase/struct/index.php	Fri Aug  9 19:04:33 2013	(r924)
+++ wwwbase/struct/index.php	Mon Aug 12 17:11:45 2013	(r925)
@@ -1,12 +1,26 @@
 <?php
 require_once("../../phplib/util.php");
 
+// Select the first 500 lexems with short definitions and present 20 of them at random.
+// It's hard to select all the easy lexems because the query is very slow.
+define('NUM_EASY_LEXEMS', 500);
+define('NUM_EASY_LEXEMS_SHOWN', 20);
+
 $easyLexems = Model::factory('Lexem')
   ->raw_query('select l.* from Lexem l, LexemDefinitionMap ldm, Definition d ' .
               'where l.id = ldm.lexemId and ldm.definitionId = d.id and d.status = 0 ' .
-              'group by l.id having sum(char_length(internalRep)) <= 100 limit 10')
+              'group by l.id having sum(char_length(internalRep)) <= 100 limit ' . NUM_EASY_LEXEMS)
   ->find_many();
 
+// Now select NUM_EASY_LEXEMS_SHOWN of them at random
+for ($i = 0; $i < NUM_EASY_LEXEMS_SHOWN; $i++) {
+  $j = rand($i, NUM_EASY_LEXEMS - 1);
+  $tmp = $easyLexems[$i];
+  $easyLexems[$i] = $easyLexems[$j];
+  $easyLexems[$j] = $tmp;
+}
+array_splice($easyLexems, NUM_EASY_LEXEMS_SHOWN);
+
 SmartyWrap::assign('easyLexems', $easyLexems);
 SmartyWrap::assign('sectionTitle', 'Structurare definiții');
 SmartyWrap::addCss('select2');


More information about the Dev mailing list