taxonomy_manager.admin.inc 106 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830
  1. <?php
  2. /**
  3. *
  4. * @file
  5. * Taxonomy Manager Admin
  6. *
  7. * contains all forms and saving function for the Taxonomy Manager
  8. *
  9. */
  10. include_once DRUPAL_ROOT . "/modules/taxonomy/taxonomy.admin.inc";
  11. /**
  12. * list of vocabularies, which link to Taxonomy Manager interface
  13. */
  14. function taxonomy_manager_voc_list() {
  15. $output = l(t('Add new vocabulary'), 'admin/structure/taxonomy/add/vocabulary') . ' | ';
  16. $output .= l(t('Edit vocabulary settings'), 'admin/structure/taxonomy') . '<br /><br />';
  17. $vocabularies = taxonomy_get_vocabularies();
  18. $voc_list = array();
  19. foreach ($vocabularies as $vocabulary) {
  20. $voc_list[] = l($vocabulary->name, 'admin/structure/taxonomy_manager/voc/' . $vocabulary->machine_name);
  21. }
  22. if (!count($voc_list)) {
  23. $voc_list[] = t('No Vocabularies available');
  24. }
  25. $output .= theme('item_list', array('items' => $voc_list, 'title' => t('Vocabularies')));
  26. return $output;
  27. }
  28. /**
  29. * defines forms for taxonomy manager interface
  30. *
  31. * @param $voc vocabulary
  32. * @param $tid a term id, if not 0, displays term editing from for given tid on right side
  33. * @param $search_string a string to filter root level terms
  34. */
  35. function taxonomy_manager_form($form, &$form_state, $voc, $tid = 0, $filter = NULL) {
  36. // Check for confirmation forms.
  37. if (isset($form_state['confirm_delete'])) {
  38. return taxonomy_manager_term_confirm_delete($form, $form_state, $voc->vid);
  39. }
  40. // By default use tid from term data form, except it is submitted from the load-tid helper and the tree needs to be refreshed.
  41. if (isset($form_state['values']['tid']) && !(isset($form_state['triggering_element']['#value']) && $form_state['triggering_element']['#value'] == "load term" && $form_state['values']['load-tid-refresh-tree'])) {
  42. $tid = $form_state['values']['tid'];
  43. }
  44. elseif (isset($form_state['triggering_element']['#value']) && $form_state['triggering_element']['#value'] == "load term" && $form_state['values']['load-tid-refresh-tree']) {
  45. $tid = $form_state['values']['load-tid'];
  46. }
  47. $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  48. $form['#attached']['css'][] = $module_path . 'css/taxonomy_manager.css';
  49. $form['#attached']['js'][] = $module_path . 'js/hideForm.js';
  50. $form['#attached']['js'][] = $module_path . 'js/updateWeight.js';
  51. $form['#attached']['js'][] = $module_path . 'js/termData.js';
  52. $form['#attached']['js'][] = array('data' => array('termData' => array('url' => url("admin/structure/taxonomy_manager/termdata/edit/" . $voc->vid))), 'type' => 'setting');
  53. $form['#attached']['js'][] = array('data' => array('updateWeight' => array('up' => 'edit-weight-up', 'down' => 'edit-weight-down', 'url' => url('admin/structure/taxonomy_manager/weight/'), 'disable_mouseover' => variable_get('taxonomy_manager_disable_mouseover', 0))), 'type' => 'setting');
  54. $form['#attached']['js'][] = array('data' => array('TMAjaxThrobber' => array('add' => TRUE)), 'type' => 'setting');
  55. $form['#attached']['js'][] = array('data' => array('taxonomy_manager' => array('modulePath' => (url($module_path) == $module_path) ? $module_path : (base_path() . $module_path))), 'type' => 'setting');
  56. drupal_set_title(t("Taxonomy Manager - %voc_name", array("%voc_name" => $voc->name)), PASS_THROUGH);
  57. $form['voc'] = array('#type' => 'value', "#value" => $voc);
  58. // Helper forms for loading the term data form.
  59. // When a term link in the tree view gets clicked, the term id is written into the
  60. // load-tid textfield and aftwards the load-tid-submit button gets clicked, which
  61. // triggers the ajax system.
  62. $form['load-tid'] = array(
  63. '#type' => 'textfield',
  64. '#prefix' => '<div class="taxonomy-manager-term-load-helper">',
  65. );
  66. $form['load-tid-refresh-tree'] = array(
  67. '#type' => 'checkbox',
  68. );
  69. $form['load-tid-submit'] = array(
  70. '#type' => 'submit',
  71. '#value' => 'load term',
  72. '#submit' => array('taxonomy_manager_load_tid_submit'),
  73. '#ajax' => array(
  74. 'callback' => 'taxonomy_manager_term_data_form_ajax_callback',
  75. 'method' => 'replaceWith',
  76. 'event' => 'click',
  77. 'wrapper' => 'taxonomy-term-data-replace',
  78. ),
  79. '#suffix' => '</div>',
  80. );
  81. taxonomy_manager_form_voc_jumper($form, $form_state);
  82. if (_taxonomy_manager_voc_is_empty($voc->vid)) {
  83. $text = t('No terms available');
  84. $form['text'] = array(
  85. '#markup' => $text,
  86. );
  87. taxonomy_manager_add_form($form, $voc, FALSE);
  88. return $form;
  89. }
  90. $form_state['cache'] = TRUE;
  91. $form['taxonomy']['#tree'] = TRUE;
  92. $form['taxonomy']['manager'] = array(
  93. '#type' => 'fieldset',
  94. '#title' => check_plain($voc->name) . _taxonomy_manager_select_all_helpers_markup(),
  95. '#weight' => 10,
  96. '#tree' => TRUE,
  97. );
  98. $form['taxonomy']['manager']['top'] = array(
  99. '#markup' => '',
  100. '#prefix' => '<div class="taxonomy-manager-tree-top">',
  101. '#suffix' => '</div>',
  102. );
  103. if (module_exists('i18n_taxonomy')) {
  104. if (i18n_taxonomy_vocabulary_mode($voc->vid, I18N_MODE_TRANSLATE)) {
  105. if ($tid) {
  106. $language = _taxonomy_manager_term_get_lang($tid);
  107. }
  108. else {
  109. $language = language_default()->language;
  110. }
  111. $form['taxonomy']['manager']['top']['language'] = array(
  112. '#type' => 'select',
  113. '#title' => t('Language'),
  114. '#default_value' => $language,
  115. '#options' => array('' => t('All'), 'no language' => t('no language')) + locale_language_list('name'),
  116. '#attributes' => array('class' => array('language-selector')),
  117. );
  118. }
  119. }
  120. $form['taxonomy']['manager']['top']['size'] = array('#markup' => '<div class="taxonomy-manager-tree-size">' . theme("image", array('path' => $module_path . "images/grippie.png", 'alt' => t("Resize tree"), 'title' => t("Resize tree"), 'attributes' => array('class' => "div-grippie"))) . '</div>');
  121. if (isset($form_state['values']['double_tree_values']['left_tree_expand_terms']) && count($form_state['values']['double_tree_values']['left_tree_expand_terms'])) {
  122. $tids_to_expand = $form_state['values']['double_tree_values']['left_tree_expand_terms'];
  123. }
  124. elseif (isset($form_state['values']['searched_terms']) && count($form_state['values']['searched_terms'])) {
  125. $tids_to_expand = $form_state['values']['searched_terms'];
  126. }
  127. else {
  128. $tids_to_expand = $tid;
  129. }
  130. $form['taxonomy']['manager']['tree'] = array(
  131. '#type' => 'taxonomy_manager_tree',
  132. '#vid' => $voc->vid,
  133. '#pager' => TRUE,
  134. '#search_string' => ($tid) ? NULL : $filter,
  135. '#language' => isset($language) ? $language : '',
  136. '#terms_to_expand' => $tids_to_expand,
  137. '#terms_to_highlight' => $tids_to_expand,
  138. );
  139. $form['toolbar'] = array(
  140. '#type' => 'fieldset',
  141. '#title' => t('Toolbar'),
  142. );
  143. $form['toolbar']['weight_up'] = array(
  144. //'#type' => 'button',
  145. '#attributes' => array('class' => array('taxonomy-manager-buttons')),
  146. '#value' => t('Up'),
  147. '#theme' => 'no_submit_button',
  148. '#prefix' => '<div id="taxonomy-manager-toolbar-buttons">',
  149. );
  150. $form['toolbar']['weight-down'] = array(
  151. //'#type' => 'button',
  152. '#attributes' => array('class' => array('taxonomy-manager-buttons')),
  153. '#value' => t('Down'),
  154. '#theme' => 'no_submit_button',
  155. );
  156. $form['toolbar']['wrapper'] = array(
  157. '#type' => 'markup',
  158. '#markup' => '<div id="taxonomy-manager-toolbar-throbber"></div><div class="clear"></div>',
  159. '#weight' => 20,
  160. '#prefix' => '</div>',
  161. );
  162. taxonomy_manager_add_form($form, $voc);
  163. taxonomy_manager_confirm_delete($form, $voc);
  164. taxonomy_manager_term_merge_form($form, $voc);
  165. taxonomy_manager_move_form($form, $voc);
  166. taxonomy_manager_export_form($form, $form_state, $voc);
  167. taxonomy_manager_double_tree_settings_form($form, $voc);
  168. taxonomy_manager_search_form($form, $voc);
  169. // A term clicked in tree-view and submitted through load-tid helper,
  170. // generate term data form.
  171. // Moved this code snippet to the bottom here to prevent needless
  172. // expanding of the tree for this tid.
  173. if (isset($form_state['values']['load-tid'])) {
  174. $tid = $form_state['values']['load-tid'];
  175. }
  176. // Something on the term data has been submitted, e.g. the 'add another item'
  177. // button
  178. elseif (isset($form_state['term']) && is_object($form_state['term'])) {
  179. $tid = $form_state['term']->tid;
  180. }
  181. taxonomy_manager_term_data_form($form, $form_state, $tid, $voc->vid);
  182. return $form;
  183. }
  184. function taxonomy_manager_double_tree_form($form, &$form_state, $voc1, $voc2, $tid = 0, $filter = NULL) {
  185. // Check for confirmation forms.
  186. if (isset($form_state['confirm_delete'])) {
  187. return taxonomy_manager_term_confirm_delete($form, $form_state, $voc1->vid, $voc2->vid);
  188. }
  189. $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  190. $form = taxonomy_manager_form($form, $form_state, $voc1, $tid, $filter);
  191. $form['disable'] = array(
  192. '#markup' => l(t('Disable Double Tree'), 'admin/structure/taxonomy_manager/voc/ ' . $voc1->machine_name),
  193. '#weight' => -100,
  194. );
  195. $form['voc2'] = array('#type' => 'value', "#value" => $voc2);
  196. $form['taxonomy2'] = array(
  197. '#tree' => TRUE,
  198. );
  199. $form['taxonomy2']['manager'] = array(
  200. '#type' => 'fieldset',
  201. '#title' => check_plain($voc2->name) . _taxonomy_manager_select_all_helpers_markup(),
  202. '#weight' => 10,
  203. '#tree' => TRUE,
  204. );
  205. $form['taxonomy2']['manager']['top'] = array(
  206. '#value' => '',
  207. '#prefix' => '<div class="taxonomy-manager-tree-top">',
  208. '#suffix' => '</div>',
  209. );
  210. if (module_exists('i18n_taxonomy')) {
  211. if (i18n_taxonomy_vocabulary_mode($voc2->vid, I18N_MODE_TRANSLATE)) {
  212. if ($tid) {
  213. $language = _taxonomy_manager_term_get_lang($tid);
  214. }
  215. else {
  216. $language = language_default()->language;
  217. }
  218. $form['taxonomy2']['manager']['top']['language'] = array(
  219. '#type' => 'select',
  220. '#title' => t('Language'),
  221. '#default_value' => $language,
  222. '#options' => array('' => t('All'), 'no language' => t('no language')) + locale_language_list('name'),
  223. '#attributes' => array('class' => array('language-selector')),
  224. );
  225. }
  226. }
  227. $form['taxonomy2']['manager']['top']['size'] = array('#markup' => '<div class="taxonomy-manager-tree-size">' . theme("image", array('path' => $module_path . "images/grippie.png", 'alt' => t("Resize tree"), 'title' => t("Resize tree"), 'attributes' => array('class' => "div-grippie"))) . '</div>');
  228. if (isset($form_state['values']['double_tree_values']['right_tree_expand_terms']) && count($form_state['values']['double_tree_values']['right_tree_expand_terms'])) {
  229. $tids_to_expand = $form_state['values']['double_tree_values']['right_tree_expand_terms'];
  230. }
  231. else {
  232. $tids_to_expand = $tid;
  233. }
  234. $form['taxonomy2']['manager']['tree'] = array(
  235. '#type' => 'taxonomy_manager_tree',
  236. '#vid' => $voc2->vid,
  237. '#pager' => TRUE,
  238. '#search_string' => ($tid) ? NULL : $filter,
  239. '#language' => isset($language) ? $language : '',
  240. '#terms_to_expand' => $tids_to_expand, //@todo check if term coming through ajax
  241. '#terms_to_highlight' => $tids_to_expand,
  242. );
  243. $form['double-tree']['operations'] = array(
  244. '#tree' => TRUE,
  245. );
  246. $form['double-tree']['operations']['move_right'] = array(
  247. '#type' => 'image_button',
  248. '#attributes' => array('title' => t('Move right')),
  249. '#src' => $module_path . "images/go-next.png",
  250. '#submit' => array('taxonomy_manager_double_tree_move_submit'),
  251. '#validate' => array('taxonomy_manager_double_tree_move_validate'),
  252. '#ajax' => array(
  253. 'callback' => 'taxonomy_manager_double_tree_ajax_callback',
  254. 'method' => 'replaceWith',
  255. 'event' => 'click',
  256. 'wrapper' => 'taxonomy-manager',
  257. 'progress' => array('type' => ''),
  258. ),
  259. '#weight' => 20,
  260. '#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">',
  261. '#suffix' => '</div>',
  262. );
  263. $form['double-tree']['operations']['move_left'] = array(
  264. '#type' => 'image_button',
  265. '#attributes' => array('title' => t('Move left')),
  266. '#src' => $module_path . "images/go-previous.png",
  267. '#submit' => array('taxonomy_manager_double_tree_move_submit'),
  268. '#validate' => array('taxonomy_manager_double_tree_move_validate'),
  269. '#ajax' => array(
  270. 'callback' => 'taxonomy_manager_double_tree_ajax_callback',
  271. 'method' => 'replaceWith',
  272. 'event' => 'click',
  273. 'wrapper' => 'taxonomy-manager',
  274. 'progress' => array('type' => ''),
  275. ),
  276. '#weight' => 20,
  277. '#prefix' => '<div class="taxonomy-manager-double-tree-operations-buttons">',
  278. '#suffix' => '</div>',
  279. );
  280. //switch operations
  281. if ($voc1->vid != $voc2->vid) {
  282. $form['double-tree']['operations']['move_right']['#attributes']['title'] = t('Switch selected terms and its children to the right voc');
  283. $form['double-tree']['operations']['move_right']['#submit'] = array('taxonomy_manager_double_tree_switch_submit');
  284. $form['double-tree']['operations']['move_right']['#validate'] = array('taxonomy_manager_double_tree_switch_validate');
  285. $form['double-tree']['operations']['move_left']['#attributes']['title'] = t('Switch selected terms and its children to the left voc');
  286. $form['double-tree']['operations']['move_left']['#submit'] = array('taxonomy_manager_double_tree_switch_submit');
  287. $form['double-tree']['operations']['move_left']['#validate'] = array('taxonomy_manager_double_tree_switch_validate');
  288. // Copy buttons
  289. $form['double-tree']['operations']['copy_right'] = $form['double-tree']['operations']['move_right'];
  290. $form['double-tree']['operations']['copy_left'] = $form['double-tree']['operations']['move_left'];
  291. $form['double-tree']['operations']['copy_right']['#attributes']['title'] = t('Copy selected term names to the right voc.');
  292. $form['double-tree']['operations']['copy_right']['#src'] = $module_path . "images/copy-right.png";
  293. $form['double-tree']['operations']['copy_right']['#submit'] = array('taxonomy_manager_double_tree_copy_submit');
  294. $form['double-tree']['operations']['copy_right']['#validate'] = array('taxonomy_manager_double_tree_copy_validate');
  295. $form['double-tree']['operations']['copy_right']['#weight'] = 22;
  296. $form['double-tree']['operations']['copy_left']['#attributes']['title'] = t('Copy selected term names to the left voc.');
  297. $form['double-tree']['operations']['copy_left']['#src'] = $module_path . "images/copy-left.png";
  298. $form['double-tree']['operations']['copy_left']['#submit'] = array('taxonomy_manager_double_tree_copy_submit');
  299. $form['double-tree']['operations']['copy_left']['#validate'] = array('taxonomy_manager_double_tree_copy_validate');
  300. $form['double-tree']['operations']['copy_left']['#weight'] = 23;
  301. }
  302. elseif (module_exists('i18n_taxonomy') && i18n_taxonomy_vocabulary_mode($voc2->vid, I18N_MODE_TRANSLATE)) {
  303. $form['double-tree']['operations']['add_translation'] = $form['double-tree']['operations']['move_right'];
  304. $form['double-tree']['operations']['add_translation']['#attributes']['title'] = t('Add Translation.');
  305. $form['double-tree']['operations']['add_translation']['#src'] = $module_path . "images/connect.png";
  306. $form['double-tree']['operations']['add_translation']['#submit'] = array('taxonomy_manager_double_tree_add_translation_submit');
  307. $form['double-tree']['operations']['add_translation']['#validate'] = array('taxonomy_manager_double_tree_add_translation_validate');
  308. }
  309. return $form;
  310. }
  311. /**
  312. * Adds a voc jumper menu, if ctools is enabled.
  313. */
  314. function taxonomy_manager_form_voc_jumper(&$form, $form_state) {
  315. if (module_exists('ctools')) {
  316. $options = array();
  317. foreach (taxonomy_vocabulary_get_names() as $voc) {
  318. $options[url('admin/structure/taxonomy_manager/voc/' . $voc->machine_name)] = $voc->name;
  319. }
  320. ctools_include('jump-menu');
  321. $settings = array(
  322. 'choose' => t('-- Switch vocabulary --'),
  323. );
  324. $form = ctools_jump_menu($form, $form_state, $options, $settings);
  325. // Attach the JS in case we rebuild the form.
  326. $form['#attached']['js'][] = drupal_get_path('module', 'ctools') . '/js/jump-menu.js';
  327. }
  328. }
  329. /**
  330. * form for searching terms
  331. */
  332. function taxonomy_manager_search_form(&$form, $voc) {
  333. $form['#attached']['js'][] = array(
  334. 'data' => array('hideForm' => array(array(
  335. 'show_button' => 'edit-search-show',
  336. 'hide_button' => 'edit-search-cancel',
  337. 'div' => 'edit-search'))),
  338. 'type' => 'setting');
  339. $form['toolbar']['search_show'] = array(
  340. //'#type' => 'button',
  341. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'search')),
  342. '#value' => t('Search'),
  343. '#theme' => 'no_submit_button',
  344. );
  345. $search_description = t("You can search directly for exisiting terms.
  346. If your input doesn't match an existing term, it will be used for filtering root level terms (useful for non-hierarchical vocabularies).");
  347. $form['search'] = array(
  348. '#type' => 'fieldset',
  349. '#title' => t('Search'),
  350. '#attributes' => array('style' => 'display:none;', 'id' => 'edit-search'),
  351. '#description' => $search_description,
  352. '#collapsed' => TRUE,
  353. '#tree' => TRUE,
  354. );
  355. $form['search']['field'] = array(
  356. '#type' => 'textfield',
  357. '#title' => t('Search String'),
  358. '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid,
  359. //'#prefix' => '<div id="edit-find-field">',
  360. //'#suffix' => '</div>',
  361. );
  362. $search_options = array(
  363. //'synonyms' => t('Include synonyms'), // @todo implement synonyms feature
  364. 'subtrees' => t('Search under selected terms'),
  365. );
  366. if (module_exists('i18n_taxonomy')) {
  367. if (i18n_taxonomy_vocabulary_mode($voc->vid, I18N_MODE_TRANSLATE)) {
  368. $search_options['language'] = t('Search within selected language');
  369. }
  370. }
  371. $form['search']['options'] = array(
  372. '#type' => 'checkboxes',
  373. '#title' => t('Search options'),
  374. '#options' => $search_options,
  375. );
  376. $form['search']['button'] = array(
  377. '#type' => 'submit',
  378. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'search')),
  379. '#value' => t('Search'),
  380. //'#suffix' => '<div class="clear"></div>',
  381. );
  382. $form['search']['cancel'] = array(
  383. //'#type' => 'button',
  384. '#value' => t('Cancel'),
  385. '#theme' => 'no_submit_button',
  386. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  387. );
  388. }
  389. /**
  390. * confirmation form for deleting selected terms
  391. */
  392. function taxonomy_manager_confirm_delete(&$form, $voc) {
  393. $form['#attached']['js'][] = array(
  394. 'data' => array('hideForm' => array(array(
  395. 'show_button' => 'edit-delete-confirm',
  396. 'hide_button' => 'edit-delete-cancel',
  397. 'div' => 'edit-delete'))),
  398. 'type' => 'setting');
  399. $form['toolbar']['delete_confirm'] = array(
  400. //'#type' => 'button',
  401. '#attributes' => array('class' => array('taxonomy-manager-buttons delete')),
  402. '#value' => t('Delete'),
  403. '#theme' => 'no_submit_button',
  404. );
  405. $form['delete'] = array(
  406. '#type' => 'fieldset',
  407. '#attributes' => array('style' => 'display:none;', 'id' => 'edit-delete'),
  408. '#tree' => TRUE,
  409. '#title' => t('Confirmation'),
  410. );
  411. $question = t('Are you sure you want to delete all selected terms?');
  412. $info = t('Remember all term specific data will be lost. This action cannot be undone.');
  413. $form['delete']['text'] = array('#value' => "<b>" . $question . "</b><br/>" . $info);
  414. $options = array(
  415. 'delete_orphans' => t('Delete children of selected terms, if there are any'),
  416. );
  417. $form['delete']['options'] = array(
  418. '#type' => 'checkboxes',
  419. '#title' => t('Options'),
  420. '#options' => $options,
  421. );
  422. $form['delete']['delete'] = array(
  423. '#type' => 'submit',
  424. '#value' => t('Delete'),
  425. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'delete')),
  426. '#submit' => array('taxonomy_manager_form_delete_submit'),
  427. '#validate' => array('taxonomy_manager_form_delete_validate'),
  428. );
  429. $form['delete']['cancel'] = array(
  430. //'#type' => 'button',
  431. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  432. '#value' => t('Cancel'),
  433. '#theme' => 'no_submit_button',
  434. );
  435. }
  436. /**
  437. * form for adding terms
  438. */
  439. function taxonomy_manager_add_form(&$form, $voc, $hide_form = TRUE) {
  440. $attributes = array();
  441. if ($hide_form) {
  442. $form['#attached']['js'][] = array(
  443. 'data' => array('hideForm' => array(array(
  444. 'show_button' => 'edit-add-show',
  445. 'hide_button' => 'edit-add-cancel',
  446. 'div' => 'edit-add'))),
  447. 'type' => 'setting');
  448. $attributes = array('style' => 'display:none;', 'id' => 'edit-add');
  449. $form['toolbar']['add_show'] = array(
  450. //'#type' => 'button',
  451. '#attributes' => array('class' => 'taxonomy-manager-buttons add'),
  452. '#value' => t('Add'),
  453. '#theme' => 'no_submit_button',
  454. );
  455. }
  456. $description = "";
  457. $description = t("If you have selected one or more terms in the tree view, the new terms are automatically children of those.");
  458. $form['add'] = array(
  459. '#type' => 'fieldset',
  460. '#tree' => TRUE,
  461. '#attributes' => $attributes,
  462. '#title' => t('Add new terms'),
  463. '#description' => $description,
  464. );
  465. $form['add']['mass_add'] = array(
  466. '#type' => 'textarea',
  467. '#title' => t('Terms'),
  468. '#description' => t("One term per line. Child terms can be prefixed with a
  469. dash '-' (one dash per hierarchy level). Terms that should not become
  470. child terms and start with a dash need to be wrapped in double quotes.
  471. <br />Example:<br />
  472. animals<br />
  473. -canine<br />
  474. --dog<br />
  475. --wolf<br />
  476. -feline<br />
  477. --cat"),
  478. '#rows' => 10,
  479. );
  480. $form['add']['add'] = array(
  481. '#type' => 'submit',
  482. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'add')),
  483. '#value' => t('Add'),
  484. '#submit' => array('taxonomy_manager_form_add_submit'),
  485. );
  486. $form['add']['cancel'] = array(
  487. //'#type' => 'button',
  488. '#value' => t('Cancel'),
  489. '#theme' => 'no_submit_button',
  490. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  491. );
  492. }
  493. /**
  494. * Form for the Term merge module
  495. */
  496. function taxonomy_manager_term_merge_form(&$form, $voc) {
  497. if (!module_exists('term_merge') || !user_access('merge terms')) {
  498. return;
  499. }
  500. $form['#attached']['js'][] = array(
  501. 'data' => array('hideForm' => array(array(
  502. 'show_button' => 'edit-term-merge-show',
  503. 'hide_button' => 'edit-term-merge-cancel',
  504. 'div' => 'edit-term-merge'))),
  505. 'type' => 'setting');
  506. $description = t("This operation is based on the Term merge module. Selected terms get merged into the given one. Optionally the selected terms can be retained, otherwise they will be deleted.");
  507. $form['toolbar']['term_merge_show'] = array(
  508. //'#type' => 'button',
  509. '#attributes' => array('class' => array('taxonomy-manager-buttons merge')),
  510. '#value' => t('Term merge'),
  511. '#theme' => 'no_submit_button',
  512. );
  513. $form['term_merge'] = array(
  514. '#type' => 'fieldset',
  515. '#tree' => TRUE,
  516. '#attributes' => array('style' => 'display:none;', 'id' => 'edit-term-merge'),
  517. '#title' => t('Merging of terms'),
  518. '#description' => $description,
  519. );
  520. $form['term_merge']['dest_term'] = array(
  521. '#type' => 'textfield',
  522. '#title' => t('Destination term'),
  523. '#description' => t("Enter a unique term name or a term id with 'term-id:[tid]'"),
  524. '#required' => FALSE,
  525. '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid,
  526. );
  527. $form['term_merge']['options'] = array(
  528. '#type' => 'checkboxes',
  529. '#title' => t('Options'),
  530. '#options' => array(
  531. 'keep_merged' => t('Keep merged terms'),
  532. ),
  533. );
  534. $form['term_merge']['submit'] = array(
  535. '#type' => 'submit',
  536. '#value' => t('Merge'),
  537. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'merge')),
  538. '#validate' => array('taxonomy_manager_form_term_merge_validate'),
  539. '#submit' => array('taxonomy_manager_form_term_merge_submit'),
  540. );
  541. $form['term_merge']['cancel'] = array(
  542. //'#type' => 'button',
  543. '#value' => t('Cancel'),
  544. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  545. '#theme' => 'no_submit_button',
  546. );
  547. }
  548. /**
  549. * form for moving terms in hierarchies
  550. */
  551. function taxonomy_manager_move_form(&$form, $voc) {
  552. $form['#attached']['js'][] = array(
  553. 'data' => array('hideForm' => array(array(
  554. 'show_button' => 'edit-move-show',
  555. 'hide_button' => 'edit-move-cancel',
  556. 'div' => 'edit-move'))),
  557. 'type' => 'setting');
  558. $description = t("You can change the parent of one or more selected terms.
  559. If you leave the autocomplete field empty, the term will be a root term.");
  560. $form['toolbar']['move_show'] = array(
  561. //'#type' => 'button',
  562. '#value' => t('Move'),
  563. '#attributes' => array('class' => array('taxonomy-manager-buttons move')),
  564. '#theme' => 'no_submit_button',
  565. );
  566. $form['move'] = array(
  567. '#type' => 'fieldset',
  568. '#tree' => TRUE,
  569. '#attributes' => array('style' => 'display:none;', 'id' => 'edit-move'),
  570. '#title' => t('Moving of terms'),
  571. '#description' => $description,
  572. );
  573. $form['move']['parents'] = array(
  574. '#type' => 'textfield',
  575. '#title' => t('Parent term(s)'),
  576. '#description' => t("Enter a unique term name or a term id with 'term-id:[tid]'. Separate multiple parent terms with commas."),
  577. '#required' => FALSE,
  578. '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $voc->vid,
  579. );
  580. $options = array();
  581. $options['keep_old_parents'] = t('Keep old parents and add new ones (multi-parent). Otherwise old parents get replaced.');
  582. $form['move']['options'] = array(
  583. '#type' => 'checkboxes',
  584. '#title' => t('Options'),
  585. '#options' => $options,
  586. );
  587. $form['move']['submit'] = array(
  588. '#type' => 'submit',
  589. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'move')),
  590. '#value' => t('Move'),
  591. '#validate' => array('taxonomy_manager_form_move_validate'),
  592. '#submit' => array('taxonomy_manager_form_move_submit'),
  593. );
  594. $form['move']['cancel'] = array(
  595. //'#type' => 'button',
  596. '#value' => t('Cancel'),
  597. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  598. '#theme' => 'no_submit_button',
  599. );
  600. }
  601. /**
  602. * form for exporting terms
  603. */
  604. function taxonomy_manager_export_form(&$form, &$form_state, $voc) {
  605. $form['#attached']['js'][] = array(
  606. 'data' => array('hideForm' => array(array(
  607. 'show_button' => 'edit-export-show',
  608. 'hide_button' => 'edit-export-cancel',
  609. 'div' => 'edit-export'))),
  610. 'type' => 'setting',
  611. );
  612. $form['toolbar']['export_show'] = array(
  613. //'#type' => 'button',
  614. '#attributes' => array('class' => array('taxonomy-manager-buttons export')),
  615. '#value' => t('Export'),
  616. '#theme' => 'no_submit_button',
  617. );
  618. $form['export'] = array(
  619. '#type' => 'fieldset',
  620. '#tree' => TRUE,
  621. '#attributes' => array('style' => 'display:none;', 'id' => 'edit-export'),
  622. '#title' => t('Export'),
  623. );
  624. $scope_options = array(
  625. 'whole_voc' => t('Whole Vocabulary'),
  626. 'children' => t('Child terms of a selected term'),
  627. 'root_terms' => t('Root level terms only'),
  628. );
  629. $form['export']['scope'] = array(
  630. '#type' => 'radios',
  631. '#title' => t('Terms to export'),
  632. '#options' => $scope_options,
  633. '#default_value' => 'whole_voc',
  634. '#prefix' => '<div id="taxonomy_manager_export_options">',
  635. '#suffix' => '</div>',
  636. );
  637. $form['export']['depth'] = array(
  638. '#type' => 'textfield',
  639. '#title' => t('Depth of tree'),
  640. '#description' => t('The number of levels of the tree to export. Leave empty to return all levels.'),
  641. '#size' => 10,
  642. );
  643. $format_options = array(
  644. 'term_tree' => t('Term names with hierarchy'),
  645. 'csv' => t('CSV'),
  646. );
  647. $help_items[] = t('Term names with hierarchy: Only term names are exported. Child terms are prefixed with dashes. Uses the same format as for mass-import (Add button).');
  648. $help_items[] = t('CSV: The comma-separated-values export has following columns: voc id | term id | term name | description | parent id 1 | ... | parent id n');
  649. $form['export']['format'] = array(
  650. '#type' => 'radios',
  651. '#title' => t('Format'),
  652. '#options' => $format_options,
  653. '#default_value' => 'term_tree',
  654. '#description' => theme('item_list', array('items' => $help_items, 'title' => t('Description of formats'))),
  655. );
  656. // CSV options
  657. $form['export']['csv']['delimiter'] = array(
  658. '#type' => 'textfield',
  659. '#title' => t('Delimiter for CSV'),
  660. '#required' => FALSE,
  661. '#default_value' => ";",
  662. '#size' => 10,
  663. '#states' => array(
  664. 'visible' => array(
  665. ':input[name="export[format]"]' => array('value' => 'csv'),
  666. ),
  667. ),
  668. );
  669. $wrapper_id = 'taxonomy-manager-export-textarea';
  670. if (isset($form_state['values']['export']['data'])) {
  671. $form['export']['data'] = array(
  672. '#type' => 'textarea',
  673. '#title' => t('Exported data'),
  674. '#value' => $form_state['values']['export']['data'],
  675. '#rows' => 8,
  676. '#prefix' => '<div id="' . $wrapper_id . '">',
  677. '#suffix' => '</div>',
  678. );
  679. }
  680. $form['export']['submit'] = array(
  681. '#prefix' => '<div id="' . $wrapper_id . '"></div>',
  682. '#type' => 'submit',
  683. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'export')),
  684. '#value' => t('Export now'),
  685. '#submit' => array('taxonomy_manager_export_form_submit'),
  686. '#ajax' => array(
  687. 'callback' => 'taxonomy_manager_export_ajax_callback',
  688. 'method' => 'replaceWith',
  689. 'event' => 'click',
  690. 'wrapper' => $wrapper_id,
  691. 'progress' => array('type' => ''),
  692. ),
  693. );
  694. $form['export']['cancel'] = array(
  695. //'#type' => 'button',
  696. '#value' => t('Cancel'),
  697. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  698. '#theme' => 'no_submit_button',
  699. );
  700. }
  701. function taxonomy_manager_double_tree_settings_form(&$form, $voc) {
  702. $form['#attached']['js'][] = array(
  703. 'data' => array('hideForm' => array(array(
  704. 'show_button' => 'edit-double-tree-show',
  705. 'hide_button' => 'edit-double-tree-settings-cancel',
  706. 'div' => 'edit-double-tree-settings'))),
  707. 'type' => 'setting');
  708. $form['toolbar']['double_tree_show'] = array(
  709. //'#type' => 'button',
  710. '#attributes' => array('class' => array('taxonomy-manager-buttons double-tree')),
  711. '#value' => t('Double Tree'),
  712. '#theme' => 'no_submit_button',
  713. );
  714. $form['double-tree-settings'] = array(
  715. '#type' => 'fieldset',
  716. '#tree' => TRUE,
  717. '#attributes' => array('style' => 'display:none;', 'id' => 'edit-double-tree-settings'),
  718. '#title' => t('Double Tree Settings'),
  719. '#description' => t('Specify settings for second tree. Choose the same vocabulary if you want to move terms in the hierarchy or if you want to add new translations within a multilingual vocabulary. Choose a different vocabulary if you want to switch terms among these vocabularies.'),
  720. );
  721. $options = array();
  722. $vocs = taxonomy_get_vocabularies();
  723. foreach ($vocs as $v) {
  724. $options[$v->machine_name] = $v->name;
  725. }
  726. $form['double-tree-settings']['voc2_machine_name'] = array(
  727. '#type' => 'select',
  728. '#title' => t('Vocabulary for second tree'),
  729. '#options' => $options,
  730. '#default_value' => $voc->vid,
  731. );
  732. $form['double-tree-settings']['submit'] = array(
  733. '#type' => 'submit',
  734. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'double-tree')),
  735. '#value' => t('Enable Double Tree'),
  736. '#submit' => array('taxonomy_manager_form_double_tree_submit'),
  737. );
  738. if (arg(3) == "double-tree") {
  739. $form['double-tree-settings']['disable'] = array(
  740. '#type' => 'submit',
  741. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'double-tree-disable')),
  742. '#value' => t('Disable Double Tree'),
  743. '#submit' => array('taxonomy_manager_form_double_tree_disable_submit'),
  744. );
  745. }
  746. $form['double-tree-settings']['cancel'] = array(
  747. //'#type' => 'button',
  748. '#value' => t('Cancel'),
  749. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'cancel')),
  750. '#theme' => 'no_submit_button',
  751. );
  752. }
  753. function taxonomy_manager_term_data_form(&$form, &$form_state, $tid = 0, $vid1, $vid2 = 0) {
  754. $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  755. if ($tid) {
  756. $term = taxonomy_term_load($tid);
  757. //prevent that title of the fieldset is too long
  758. $title = check_plain($term->name);
  759. if (drupal_strlen($title) >= 33) {
  760. $title = drupal_substr($title, 0, 33) . "...";
  761. }
  762. $form['term_data'] = array(
  763. '#type' => 'fieldset',
  764. '#title' => $title . " (" . $term->tid . ")",
  765. );
  766. unset($form_state['term']);
  767. $form['term_data'] = taxonomy_form_term($form['term_data'], $form_state, $term);
  768. $form['term_data']['description']['#rows'] = 2;
  769. // Disable wysiwyg editor as long as #356480 (lazy-loading) is not resolved.
  770. $form['term_data']['description']['#wysiwyg'] = FALSE;
  771. $form['term_data']['weight'] = $form['term_data']['relations']['weight'];
  772. unset($form['term_data']['relations']);
  773. unset($form['term_data']['actions']);
  774. $form['term_data']['parents'] = _taxonomy_manager_form_term_data_parents($term);
  775. $form['term_data']['parents']['#weight'] = '52';
  776. $form['term_data']['close'] = array(
  777. '#markup' => '<div id="term-data-close"><span title="' . t('Close') . '">&nbsp;&nbsp;&nbsp;&nbsp;</span></div>',
  778. '#weight' => -100,
  779. );
  780. $link_img = theme("image", array('path' => $module_path . "images/link-small.png", 'alt' => t("link to term page")));
  781. $form['term_data']['link'] = array(
  782. '#markup' => '<br />' . l($link_img . '&nbsp;' . t('Go to the term page'), 'taxonomy/term/' . $term->tid, array('attributes' => array('rel' => 'tag', 'title' => strip_tags($term->description), 'target' => '_blank'), 'html' => TRUE)),
  783. '#weight' => 56);
  784. $form['term_data']['vid'] = array('#type' => 'hidden', '#value' => $term->vid);
  785. $form['term_data']['tid'] = array('#type' => 'hidden', '#value' => $tid);
  786. $form['term_data']['save'] = array(
  787. '#type' => 'submit',
  788. '#value' => t('Save changes'),
  789. '#submit' => array('taxonomy_manager_term_data_form_submit'),
  790. '#validate' => array('taxonomy_form_term_validate'),
  791. '#attributes' => array('class' => array('taxonomy-manager-buttons', 'save')),
  792. '#ajax' => array(
  793. 'callback' => 'taxonomy_manager_term_data_form_ajax_callback',
  794. 'method' => 'replaceWith',
  795. 'event' => 'click',
  796. 'wrapper' => 'taxonomy-term-data-replace',
  797. 'progress' => array('type' => ''),
  798. ),
  799. '#weight' => 20,
  800. );
  801. // i18n integration
  802. if (module_exists('i18n_taxonomy')) {
  803. if (i18n_taxonomy_vocabulary_mode($term->vid, I18N_MODE_TRANSLATE)) {
  804. $form['term_data']['translations'] = _taxonomy_manager_form_term_data_translations($term);
  805. $form['term_data']['translations']['#weight'] = '50';
  806. $form['term_data']['language'] = array(
  807. '#type' => 'select',
  808. '#title' => t('Language'),
  809. '#description' => t('This term belongs to a multilingual vocabulary. You can set a language for it.'),
  810. '#default_value' => $term->language,
  811. '#options' => locale_language_list('name'),
  812. );
  813. }
  814. }
  815. // UUID integration.
  816. if (module_exists('uuid')) {
  817. $uuids = entity_get_uuid_by_id('taxonomy_term', array($tid));
  818. if (count($uuids)) {
  819. $form['term_data']['uuid'] = array(
  820. '#markup' => t('UUID: @uuid', array('@uuid' => reset($uuids))),
  821. '#weight' => -10,
  822. );
  823. }
  824. }
  825. _taxonomy_manager_term_data_form_filter_file_fields($form);
  826. }
  827. $form['term_data']['#prefix'] = '<div id="taxonomy-term-data-replace">';
  828. $form['term_data']['#suffix'] = '</div>';
  829. }
  830. /**
  831. * Removes file fields from the term data form, as they do not work on the
  832. * nested form structure and link to the original term edit form instead.
  833. *
  834. * See #1195940, hack necessary until #1329856/#1468686 get fixed.
  835. */
  836. function _taxonomy_manager_term_data_form_filter_file_fields(&$form) {
  837. foreach (element_children($form['term_data']) as $key) {
  838. $field = &$form['term_data'][$key];
  839. if (isset($field['#type']) && $field['#type'] == 'container' && isset($field['#language']) && isset($field[$field['#language']])) {
  840. foreach (element_children($field[$field['#language']]) as $delta) {
  841. $element = &$field[$field['#language']][$delta];
  842. if (isset($element['#type']) && $element['#type'] == "managed_file") {
  843. $form['term_data']['file_field_info'] = array(
  844. '#markup' => '<div class="term-data-form-file-field-info">' . t('Edit file fields <a href="!url" target="_blank">here</a>.', array('!url' => url('taxonomy/term/' . $form['term_data']['#term']['tid'] . '/edit'))) . '</div>',
  845. );
  846. unset($form['term_data'][$key]);
  847. break;
  848. }
  849. }
  850. }
  851. }
  852. }
  853. /**
  854. * helper function for generating tables with values and delete op and field for adding
  855. *
  856. * @param $term term object which is going to be displayed
  857. * @return an form array
  858. */
  859. function _taxonomy_manager_form_term_data_parents($term) {
  860. $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  861. $form['#tree'] = TRUE;
  862. $form['#theme'] = 'taxonomy_manager_term_data_extra';
  863. $form['headers'][] = array('#markup' => t('Parents'));
  864. $form['headers'][] = array('#markup' => '');
  865. $form['data'] = array();
  866. foreach (taxonomy_get_parents($term->tid) as $tid => $parent) {
  867. $extra_info = taxonomy_manager_tree_term_extra_info($parent);
  868. $form['data'][$tid][] = array(
  869. '#markup' => l($parent->name, 'admin/structure/taxonomy_manager/termdata/' . $parent->tid, array('attributes' => array('title' => $extra_info, 'class' => 'taxonomy-term-data-name-link'))),
  870. '#row-class' => 'taxonomy-term-data-name',
  871. '#row-id' => 'term-' . $tid,
  872. '#tree' => TRUE,
  873. );
  874. $form['data'][$tid][0]['tid'] = array(
  875. '#type' => 'hidden',
  876. '#value' => $tid,
  877. );
  878. $form['data'][$tid]['remove'] = array(
  879. '#type' => 'image_button',
  880. '#attributes' => array('title' => t('Remove')),
  881. '#submit' => array('taxonomy_manager_term_data_form_submit_parents_remove'),
  882. '#validate' => array('taxonomy_manager_term_data_form_validate_parents_remove'),
  883. '#src' => $module_path . "images/list-remove.png",
  884. '#row-class' => 'taxonomy-term-data-operations',
  885. );
  886. $form['data'][$tid]['remove']['#ajax'] = array(
  887. 'callback' => 'taxonomy_manager_term_data_form_ajax_callback',
  888. 'progress' => array('type' => ''),
  889. 'method' => 'replaceWith',
  890. 'event' => 'click',
  891. 'wrapper' => 'taxonomy-term-data-replace',
  892. );
  893. }
  894. $form['op'] = array();
  895. $form['op']['add'] = array(
  896. '#type' => 'textfield',
  897. '#prefix' => '<div class="term-data-autocomplete">',
  898. '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $term->vid,
  899. '#suffix' => '</div>',
  900. '#size' => 35,
  901. );
  902. $form['op']['add_button'] = array(
  903. '#type' => 'image_button',
  904. '#attributes' => array('title' => t('Add')),
  905. '#submit' => array('taxonomy_manager_term_data_form_submit_parents_add'),
  906. '#validate' => array('taxonomy_manager_term_data_form_validate_parents_add'),
  907. '#src' => $module_path . "images/list-add.png",
  908. '#row-class' => 'term-data-autocomplete-add',
  909. '#ajax' => array(
  910. 'callback' => 'taxonomy_manager_term_data_form_ajax_callback',
  911. 'progress' => array('type' => ''),
  912. 'method' => 'replaceWith',
  913. 'event' => 'click',
  914. 'wrapper' => 'taxonomy-term-data-replace',
  915. ),
  916. );
  917. return $form;
  918. }
  919. /**
  920. * Helper function for generating a table listing the translations
  921. */
  922. function _taxonomy_manager_form_term_data_translations($term) {
  923. $module_path = drupal_get_path('module', 'taxonomy_manager') . '/';
  924. $languages = locale_language_list('name');
  925. $form['#tree'] = TRUE;
  926. $form['#theme'] = 'taxonomy_manager_term_data_extra';
  927. $form['headers'][] = array('#markup' => t('Translations'));
  928. $form['headers'][] = array('#markup' => t('Language'));
  929. $form['headers'][] = array('#markup' => '');
  930. if (!empty($term->i18n_tsid)) {
  931. $translation_set = i18n_taxonomy_translation_set_load($term->i18n_tsid);
  932. $translations = $translation_set->get_translations();
  933. // If the number of translations equals 1, there's only a source translation.
  934. if (count($translations) > 1) {
  935. foreach ($translations as $langcode => $translation) {
  936. if ($translation->tid !== $term->tid) {
  937. $form['data'][$translation->tid][] = array(
  938. '#markup' => l($translation->name, 'admin/structure/taxonomy_manager/termdata/' . $translation->tid, array('attributes' => array('class' => 'taxonomy-term-data-name-link'))),
  939. '#row-class' => 'taxonomy-term-data-name',
  940. '#row-id' => 'term-' . $translation->tid,
  941. '#tree' => TRUE,
  942. );
  943. $form['data'][$translation->tid][] = array(
  944. '#markup' => check_plain($languages[$translation->language]),
  945. '#row-class' => 'taxonomy-term-data-language',
  946. '#row-id' => 'term-' . $translation->language,
  947. '#tree' => TRUE,
  948. );
  949. $form['data'][$translation->tid][0]['tid'] = array(
  950. '#type' => 'hidden',
  951. '#value' => $translation->tid,
  952. );
  953. $form['data'][$translation->tid]['remove'] = array(
  954. '#type' => 'image_button',
  955. '#attributes' => array('title' => t('Remove')),
  956. '#submit' => array('taxonomy_manager_term_data_form_submit_translation_remove'),
  957. '#validate' => array('taxonomy_manager_term_data_form_validate_translation_remove'),
  958. '#src' => $module_path . "images/list-remove.png",
  959. '#row-class' => 'taxonomy-term-data-operations',
  960. );
  961. $form['data'][$translation->tid]['remove']['#ajax'] = array(
  962. 'callback' => 'taxonomy_manager_term_data_form_ajax_callback',
  963. 'progress' => array('type' => ''),
  964. 'method' => 'replaceWith',
  965. 'event' => 'click',
  966. 'wrapper' => 'taxonomy-term-data-replace',
  967. );
  968. }
  969. }
  970. }
  971. }
  972. $form['op'] = array();
  973. $form['op']['add'] = array(
  974. '#type' => 'textfield',
  975. '#prefix' => '<div class="term-data-autocomplete">',
  976. '#autocomplete_path' => 'taxonomy_manager/autocomplete/' . $term->vid,
  977. '#suffix' => '</div>',
  978. '#size' => 35,
  979. );
  980. // Translations have a different language than the original term.
  981. unset($languages[$term->language]);
  982. $form['op']['language'] = array(
  983. '#type' => 'select',
  984. '#options' => $languages,
  985. );
  986. $form['op']['add_button'] = array(
  987. '#type' => 'image_button',
  988. '#attributes' => array('title' => t('Add')),
  989. '#submit' => array('taxonomy_manager_term_data_form_submit_translation_add'),
  990. '#validate' => array('taxonomy_manager_term_data_form_validate_translation_add'),
  991. '#src' => $module_path . "images/list-add.png",
  992. '#row-class' => 'term-data-autocomplete-add',
  993. '#ajax' => array(
  994. 'callback' => 'taxonomy_manager_term_data_form_ajax_callback',
  995. 'progress' => array('type' => ''),
  996. 'method' => 'replaceWith',
  997. 'event' => 'click',
  998. 'wrapper' => 'taxonomy-term-data-replace',
  999. ),
  1000. );
  1001. return $form;
  1002. }
  1003. /**
  1004. * Returns html markup for (un)select all checkboxes buttons.
  1005. */
  1006. function _taxonomy_manager_select_all_helpers_markup() {
  1007. return '<span class="taxonomy-manager-select-helpers">' .
  1008. '<span class="select-all-children" title="' . t("Select all") . '">&nbsp;&nbsp;&nbsp;&nbsp;</span>' .
  1009. '<span class="deselect-all-children" title="' . t("Remove selection") . '">&nbsp;&nbsp;&nbsp;&nbsp;</span>' .
  1010. '</span>';
  1011. }
  1012. /**
  1013. * submit handler for loading term data form
  1014. */
  1015. function taxonomy_manager_load_tid_submit($form, &$form_state) {
  1016. // Unset input, so that the term data form has fresh values.
  1017. unset($form_state['input']);
  1018. if ($form_state['values']['load-tid-refresh-tree']) {
  1019. form_set_value(array('#parents' => array('tree-update')), array('update' => TRUE), $form_state);
  1020. }
  1021. $form_state['rebuild'] = TRUE;
  1022. }
  1023. /**
  1024. * validates the form (only search button)
  1025. **/
  1026. function taxonomy_manager_form_validate($form, &$form_state) {
  1027. if ($form_state['clicked_button']['#value'] == t('Search') && empty($form_state['values']['search']['field'])) {
  1028. form_set_error('search', t('Search field is empty'));
  1029. $form_state['rebuild'] = TRUE;
  1030. }
  1031. }
  1032. /**
  1033. * submits the taxonomy manager form (only search button)
  1034. **/
  1035. function taxonomy_manager_form_submit($form, &$form_state) {
  1036. if ($form_state['values']['delete'] === TRUE) {
  1037. return taxonomy_manager_term_confirm_delete_submit($form, $form_state);
  1038. }
  1039. $voc = $form_state['values']['voc'];
  1040. if (isset($form_state['values']['voc2'])) {
  1041. $voc2 = $form_state['values']['voc2'];
  1042. $url_prefix = 'admin/structure/taxonomy_manager/double-tree/' . $voc->machine_name . '/' . $voc2->machine_name;
  1043. }
  1044. else {
  1045. $url_prefix = 'admin/structure/taxonomy_manager/voc/' . $voc->machine_name;
  1046. }
  1047. $search_string = $form_state['values']['search']['field'];
  1048. $terms = array();
  1049. $include_synonyms = FALSE;
  1050. $selected_tids = array();
  1051. $language = "";
  1052. // @todo
  1053. /*if ($form_state['values']['search']['options']['synonyms']) {
  1054. $include_synonyms = TRUE;
  1055. }*/
  1056. if ($form_state['values']['search']['options']['subtrees']) {
  1057. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1058. }
  1059. if (isset($form_state['values']['search']['options']['language'])) {
  1060. $language = $form_state['values']['taxonomy']['manager']['top']['language'];
  1061. }
  1062. $terms = taxonomy_manager_autocomplete_search_terms($search_string, $voc->vid, $include_synonyms, $selected_tids, $language);
  1063. if (count($terms) == 1) {
  1064. $tid = $terms[0];
  1065. drupal_set_message(t("Your search string matches exactly one term"));
  1066. drupal_goto($url_prefix . '/' . $tid);
  1067. }
  1068. elseif (count($terms) > 1) {
  1069. $matched_text_list = array();
  1070. foreach ($terms as $matched_tid) {
  1071. $matched_term = taxonomy_term_load($matched_tid);
  1072. $parents = array();
  1073. foreach (taxonomy_get_parents($matched_tid) as $parent) {
  1074. $parents[] = check_plain($parent->name);
  1075. }
  1076. $parent_text = count($parents) ? implode(' | ', $parents) . " › " : "";
  1077. $matched_text_list[] = $parent_text . l($matched_term->name, $url_prefix . '/' . $matched_term->tid, array('attributes' => array('title' => taxonomy_manager_tree_term_extra_info($matched_term)))) . " (" . $matched_term->tid . (!empty($matched_term->language) ? '-' . check_plain($matched_term->language) : '') . ")";
  1078. }
  1079. form_set_value($form, array('searched_terms' => $terms), $form_state);
  1080. drupal_set_message(t("Your search string matches !count terms:", array('!count' => count($terms))) . theme('item_list', array('items' => $matched_text_list)));
  1081. $form_state['rebuild'] = TRUE;
  1082. }
  1083. else {
  1084. drupal_set_message(t("No match found. Filtering root level terms starting with @search_string.", array('@search_string' => $search_string)));
  1085. drupal_set_message(l(t("Show unfiltered tree"), $url_prefix));
  1086. drupal_goto($url_prefix . '/0/' . $search_string);
  1087. }
  1088. }
  1089. /**
  1090. * validates taxonomy manager double tree
  1091. **/
  1092. function taxonomy_manager_double_tree_form_validate($form, &$form_state) {
  1093. taxonomy_manager_form_validate($form, $form_state);
  1094. }
  1095. /**
  1096. * submits the taxonomy manager double tree
  1097. **/
  1098. function taxonomy_manager_double_tree_form_submit($form, &$form_state) {
  1099. taxonomy_manager_form_submit($form, $form_state);
  1100. }
  1101. /**
  1102. * Submit handler for adding terms
  1103. */
  1104. function taxonomy_manager_form_add_submit($form, &$form_state) {
  1105. $parents = isset($form_state['values']['taxonomy']['manager']['tree']['selected_terms']) ? $form_state['values']['taxonomy']['manager']['tree']['selected_terms'] : array();
  1106. $lang = isset($form_state['values']['taxonomy']['manager']['top']['language']) ? $form_state['values']['taxonomy']['manager']['top']['language'] : "";
  1107. $term_names_too_long = array();
  1108. $new_terms = taxonomy_manager_mass_add_terms($form_state['values']['add']['mass_add'], $form_state['values']['voc']->vid, $parents, $lang, $term_names_too_long);
  1109. $term_names = array();
  1110. foreach ($new_terms as $term) {
  1111. $term_names[] = $term->name;
  1112. }
  1113. if (module_exists('i18n_taxonomy') && !empty($lang) && i18n_taxonomy_vocabulary_mode($form_state['values']['voc']->vid, I18N_MODE_TRANSLATE)) {
  1114. drupal_set_message(t("Saving terms to language @lang", array('@lang' => locale_language_name($form_state['values']['taxonomy']['manager']['top']['language']))));
  1115. }
  1116. if (count($term_names_too_long)) {
  1117. drupal_set_message(t("Following term names were too long and truncated to 255 characters: %names.", array('%names' => implode(', ', $term_names_too_long))), 'warning');
  1118. }
  1119. drupal_set_message(t("Terms added: %terms", array('%terms' => implode(', ', $term_names))));
  1120. }
  1121. /**
  1122. * Helper function for mass adding of terms.
  1123. *
  1124. * @param $input
  1125. * The textual input with terms. Each line contains a single term. Child term
  1126. * can be prefixed with a dash '-' (one dash for each level). Term names
  1127. * starting with a dash and should not become a child term need to be wrapped
  1128. * in quotes.
  1129. * @param $vid
  1130. * The vocabulary id.
  1131. * @param int $parents
  1132. * An array of parent term ids for the new inserted terms. Can be 0.
  1133. * @param $lang
  1134. * The i18n language, if i18n exists.
  1135. * @param $term_names_too_long
  1136. * Return value that is used to indicate that some term names were too long
  1137. * and truncated to 255 characters.
  1138. *
  1139. * @return An array of the newly inserted term objects
  1140. */
  1141. function taxonomy_manager_mass_add_terms($input, $vid, $parents, $lang = "", &$term_names_too_long = array()) {
  1142. $new_terms = array();
  1143. $terms = explode("\n", str_replace("\r", '', $input));
  1144. $parents = count($parents) ? $parents : 0;
  1145. // Stores the current lineage of newly inserted terms.
  1146. $last_parents = array();
  1147. foreach ($terms as $name) {
  1148. if (empty($name)) {
  1149. continue;
  1150. }
  1151. $matches = array();
  1152. // Child term prefixed with one or more dashes
  1153. if (preg_match('/^(-){1,}/', $name, $matches)) {
  1154. $depth = strlen($matches[0]);
  1155. $name = substr($name, $depth);
  1156. $current_parents = isset($last_parents[$depth-1]) ? $last_parents[$depth-1]->tid : 0;
  1157. }
  1158. // Parent term containing dashes at the beginning and is therefore wrapped
  1159. // in double quotes
  1160. elseif (preg_match('/^\"(-){1,}.*\"/', $name, $matches)) {
  1161. $name = substr($name, 1, -1);
  1162. $depth = 0;
  1163. $current_parents = $parents;
  1164. }
  1165. else {
  1166. $depth = 0;
  1167. $current_parents = $parents;
  1168. }
  1169. // Truncate long string names that will cause database exceptions.
  1170. if (strlen($name) > 255) {
  1171. $term_names_too_long[] = $name;
  1172. $name = substr($name, 0, 255);
  1173. }
  1174. $term = new stdClass;
  1175. $term->name = $name;
  1176. $term->vid = $vid;
  1177. $term->parent = $current_parents;
  1178. if (module_exists('i18n_taxonomy') && !empty($lang) && i18n_taxonomy_vocabulary_mode($vid, I18N_MODE_TRANSLATE)) {
  1179. $term->language = $lang;
  1180. }
  1181. taxonomy_term_save($term);
  1182. $new_terms[] = $term;
  1183. $last_parents[$depth] = $term;
  1184. }
  1185. return $new_terms;
  1186. }
  1187. /**
  1188. * Validation handler for deleting terms
  1189. */
  1190. function taxonomy_manager_form_delete_validate($form, &$form_state) {
  1191. $selected_tids = array();
  1192. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1193. if (count($selected_tids) < 1) {
  1194. form_set_error('delete', t("No terms for deleting selected"));
  1195. $form_state['rebuild'] = TRUE;
  1196. }
  1197. }
  1198. /**
  1199. * Submit handler for deleting terms
  1200. */
  1201. function taxonomy_manager_form_delete_submit($form, &$form_state) {
  1202. $selected_tids = array();
  1203. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1204. if ($form_state['values']['delete'] === TRUE) {
  1205. return taxonomy_manager_term_confirm_delete_submit($form, $form_state);
  1206. }
  1207. // Rebuild the form to confirm term deletion.
  1208. $form_state['rebuild'] = TRUE;
  1209. $form_state['confirm_delete'] = TRUE;
  1210. }
  1211. /**
  1212. * Form builder for the term delete form.
  1213. *
  1214. */
  1215. function taxonomy_manager_term_confirm_delete($form, &$form_state, $vid, $vid2 = NULL) {
  1216. $voc = taxonomy_vocabulary_load($vid);
  1217. if (isset($vid2)) {
  1218. $voc2 = taxonomy_vocabulary_load($vid2);
  1219. $form['voc2'] = array('#type' => 'value', '#value' => $voc2);
  1220. $url = 'admin/structure/taxonomy_manager/double-tree/' . $voc->machine_name . '/' . $voc2->machine_name;
  1221. }
  1222. else {
  1223. $url = 'admin/structure/taxonomy_manager/voc/' . $voc->machine_name;
  1224. }
  1225. $selected = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1226. $form['selected_terms'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
  1227. foreach ($selected as $tid) {
  1228. $term = taxonomy_term_load($tid);
  1229. $form['selected_terms'][$tid] = array('#type' => 'hidden', '#value' => $tid, '#prefix' => '<li>', '#suffix' => check_plain($term->name) . "</li>\n");
  1230. }
  1231. $form['delete'] = array('#type' => 'value', '#value' => TRUE);
  1232. $form['voc'] = array('#type' => 'value', '#value' => $voc);
  1233. $form['options'] = array('#type' => 'value', '#value' => $form_state['values']['delete']['options']);
  1234. $msg = !empty($form_state['values']['delete']['options']['delete_orphans']) ? t('Deleting a term will delete all its children if there are any.') : '';
  1235. $msg .= t('This action cannot be undone.');
  1236. return confirm_form($form,
  1237. t('Are you sure you want to delete the following terms:'),
  1238. $url,
  1239. $msg,
  1240. t('Delete'),
  1241. t('Cancel'));
  1242. }
  1243. /**
  1244. * Submit handler to delete a term after confirmation.
  1245. *
  1246. */
  1247. function taxonomy_manager_term_confirm_delete_submit($form, &$form_state) {
  1248. $info = taxonomy_manager_delete_terms($form_state['values']['selected_terms'], $form_state['values']['options']);
  1249. $deleted_term_names = array();
  1250. $remaining_child_term_names = array();
  1251. foreach ($info['deleted_terms'] as $term) {
  1252. $deleted_term_names[] = $term->name;
  1253. }
  1254. foreach ($info['remaining_child_terms'] as $term) {
  1255. $remaining_child_term_names[] = $term->name;
  1256. }
  1257. if (isset($form_state['values']['voc2'])) {
  1258. $form_state['redirect'] = 'admin/structure/taxonomy_manager/double-tree/' . $form_state['values']['voc']->machine_name . '/' . $form_state['values']['voc2']->machine_name;
  1259. }
  1260. else {
  1261. $form_state['redirect'] = 'admin/structure/taxonomy_manager/voc/' . $form_state['values']['voc']->machine_name;
  1262. }
  1263. drupal_set_message(t("Deleted terms: %deleted_term_names", array('%deleted_term_names' => check_plain(implode(', ', $deleted_term_names)))));
  1264. if (count($remaining_child_term_names)) {
  1265. drupal_set_message(t("Remaining child terms with different parents: %remaining_child_term_names", array('%remaining_child_term_names' => check_plain(implode(', ', $remaining_child_term_names)))));
  1266. }
  1267. return;
  1268. }
  1269. /**
  1270. * Validation handler for moving terms
  1271. */
  1272. function taxonomy_manager_form_move_validate($form, &$form_state) {
  1273. $selected_tids = array();
  1274. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1275. $error_msg = "";
  1276. if (count($selected_tids) < 1) {
  1277. form_set_error('move', t("Please selected terms you want to move in the hierarchy"));
  1278. $form_state['rebuild'] = TRUE;
  1279. }
  1280. elseif (_taxonomy_manager_check_duplicates($form_state['values']['voc']->vid, $form_state['values']['move']['parents'], $error_msg)) {
  1281. form_set_error('move', t("Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'") . " (" . $error_msg . ").");
  1282. $form_state['rebuild'] = TRUE;
  1283. }
  1284. $typed_parents = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['move']['parents'], $form_state['values']['voc']->vid, FALSE);
  1285. $parents = array();
  1286. foreach ($typed_parents as $parent_info) {
  1287. $parents[(int) $parent_info['tid']] = (int) $parent_info['tid'];
  1288. }
  1289. if (!taxonomy_manager_check_circular_hierarchy($selected_tids, $parents)) {
  1290. form_set_error('move', t('Invalid selection. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.'));
  1291. $form_state['rebuild'] = TRUE;
  1292. }
  1293. elseif (!taxonomy_manager_check_language($form_state['values']['voc']->vid, $selected_tids, $typed_parents)) {
  1294. form_set_error('move', t('Terms must be of the same language'));
  1295. $form_state['rebuild'] = TRUE;
  1296. }
  1297. }
  1298. /**
  1299. * checks for circles in the hierarchy, e.g. 1 -> 2 -> 3 -> 1
  1300. * a term can't contain itself as a parent
  1301. *
  1302. * returns TRUE if resulting hierarchy is valid, else FALSE
  1303. */
  1304. function taxonomy_manager_check_circular_hierarchy($tids, $new_parents_tids) {
  1305. if (is_array($tids) && is_array($new_parents_tids)) {
  1306. //directly same term
  1307. foreach ($tids as $tid) {
  1308. if (in_array($tid, $new_parents_tids)) {
  1309. return FALSE;
  1310. }
  1311. }
  1312. //same term over more hierarchy levels
  1313. $all_parents = array();
  1314. foreach ($new_parents_tids as $parent_tid) {
  1315. $parents = taxonomy_get_parents_all($parent_tid);
  1316. foreach ($parents as $parent) {
  1317. $all_parents[$parent->tid] = $parent->tid;
  1318. }
  1319. }
  1320. foreach ($tids as $tid) {
  1321. if (in_array($tid, $all_parents)) {
  1322. return FALSE;
  1323. }
  1324. }
  1325. }
  1326. return TRUE;
  1327. }
  1328. /**
  1329. * checks if terms in move or merge operation are of the same language
  1330. *
  1331. * returns TRUE if operation allowed, else FALSE (different languages)
  1332. */
  1333. function taxonomy_manager_check_language($vid, $selected_tids, $parents) {
  1334. if (module_exists('i18_ntaxonomy')) {
  1335. if (count($parents) && count($selected_tids)) {
  1336. $term = array_pop($parents);
  1337. $lang = $term->language;
  1338. if (i18n_taxonomy_vocabulary_mode($voc->vid, I18N_MODE_TRANSLATE)) {
  1339. foreach ($parents as $parent) {
  1340. if (_taxonomy_manager_term_get_lang($parent['tid']) != $lang) {
  1341. return FALSE;
  1342. }
  1343. }
  1344. foreach ($selected_tids as $tid) {
  1345. if (_taxonomy_manager_term_get_lang($tid) != $lang) {
  1346. return FALSE;
  1347. }
  1348. }
  1349. }
  1350. }
  1351. }
  1352. return TRUE;
  1353. }
  1354. /**
  1355. * Submit handler for moving terms
  1356. */
  1357. function taxonomy_manager_form_move_submit($form, $form_state) {
  1358. $selected_tids = array();
  1359. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1360. $lang = isset($form_state['values']['taxonomy']['manager']['top']['language']) ? $form_state['values']['taxonomy']['manager']['top']['language'] : NULL;
  1361. $typed_parents = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['move']['parents'], $form_state['values']['voc']->vid, TRUE, $lang);
  1362. $parents = array();
  1363. foreach ($typed_parents as $parent_info) {
  1364. $parents[] = $parent_info['tid'];
  1365. }
  1366. if (count($parents) == 0) $parents[0] = 0; //if empty, delete all parents
  1367. taxonomy_manager_move($parents, $selected_tids, $form_state['values']['move']['options']);
  1368. if ($form_state['values']['move']['options']['keep_old_parents']) {
  1369. $parents[] = 1; //++ parent count for hierarchy update (-> multi hierarchy)
  1370. }
  1371. taxonomy_manager_update_voc($form_state['values']['voc']->vid, $parents);
  1372. $term_names_array = array();
  1373. foreach ($selected_tids as $selected_tid) {
  1374. $term = taxonomy_term_load($selected_tid);
  1375. $term_names_array[] = $term->name;
  1376. }
  1377. $term_names = implode(', ', $term_names_array);
  1378. $parent_names = "";
  1379. if (count($typed_parents) == 0) {
  1380. $parent_names = t("root level");
  1381. }
  1382. else {
  1383. $parent_names = $form_state['values']['move']['parents'];
  1384. }
  1385. drupal_set_message(t("Terms %term_names moved to %parent_names", array('%term_names' => $term_names, '%parent_names' => $parent_names)));
  1386. }
  1387. /**
  1388. * Validation handler for validating terms
  1389. */
  1390. function taxonomy_manager_form_term_merge_validate($form, &$form_state) {
  1391. $selected_tids = array();
  1392. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1393. $dest_terms = array();
  1394. $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  1395. preg_match_all($regexp, $form_state['values']['term_merge']['dest_term'], $matches);
  1396. $dest_terms = $matches[1];
  1397. $error_msg = "";
  1398. $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['term_merge']['dest_term'], $form_state['values']['voc']->vid, FALSE);
  1399. if (!is_array($dest_terms) || count($dest_terms) == 0 || empty($dest_terms[0])) {
  1400. form_set_error('term_merge][dest_term', t('Please enter a name into "Destination term"'));
  1401. $form_state['rebuild'] = TRUE;
  1402. }
  1403. elseif (count($dest_terms) > 1) {
  1404. form_set_error('term_merge][dest_term', t('Please only enter single names into "Destination term"'));
  1405. $form_state['rebuild'] = TRUE;
  1406. }
  1407. if (count($selected_tids) < 1) {
  1408. form_set_error('term_merge', t("Please selecte terms you want to merge"));
  1409. $form_state['rebuild'] = TRUE;
  1410. }
  1411. elseif (_taxonomy_manager_check_duplicates($form_state['values']['voc']->vid, $form_state['values']['term_merge']['dest_term'], $error_msg)) {
  1412. form_set_error('term_merge', t("Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]'") . " (" . $error_msg . ").");
  1413. $form_state['rebuild'] = TRUE;
  1414. }
  1415. }
  1416. /**
  1417. * Submit handler for term merge
  1418. */
  1419. function taxonomy_manager_form_term_merge_submit($form, $form_state) {
  1420. $selected_tids = array();
  1421. $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  1422. $dest_term_ids = taxonomy_manager_autocomplete_tags_get_tids($form_state['values']['term_merge']['dest_term'], $form_state['values']['voc']->vid, TRUE);
  1423. $dest_term_id = array_shift($dest_term_ids);
  1424. $dest_term = taxonomy_term_load($dest_term_id['tid']);
  1425. $term_names_array = array();
  1426. foreach ($selected_tids as $selected_tid) {
  1427. $term = taxonomy_term_load($selected_tid);
  1428. $term_names_array[] = $term->name;
  1429. }
  1430. $term_names = implode($term_names_array, ', ');
  1431. if (module_exists('term_merge')) {
  1432. term_merge($selected_tids, $dest_term->tid, $form_state['values']['term_merge']['options']['keep_merged']);
  1433. drupal_set_message(t("Terms %term_names merged into %dest_term", array('%term_names' => $term_names, '%dest_term' => $dest_term->name)));
  1434. }
  1435. else {
  1436. drupal_set_message(t('Term merge module not found'));
  1437. }
  1438. }
  1439. /**
  1440. * returns TRUE if term with same name exists more often
  1441. */
  1442. function _taxonomy_manager_check_duplicates($vid, $autocomplete_value, &$msg) {
  1443. $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  1444. preg_match_all($regexp, $autocomplete_value, $matches);
  1445. foreach ($matches[1] as $match) {
  1446. $terms = array();
  1447. $terms = taxonomy_manager_autocomplete_tags_get_tids($match, $vid, FALSE);
  1448. if (count($terms) > 1) {
  1449. $tids = array();
  1450. foreach ($terms as $t) {
  1451. $term = taxonomy_term_load($t['tid']);
  1452. $tids[] = $term->tid . (!empty($term->language) ? '-' . check_plain($term->language) : '');
  1453. }
  1454. $msg .= check_plain($match) . ": " . implode(", ", $tids);
  1455. return TRUE;
  1456. }
  1457. }
  1458. return FALSE;
  1459. }
  1460. function taxonomy_manager_form_double_tree_submit($form, &$form_state) {
  1461. drupal_goto('admin/structure/taxonomy_manager/double-tree/' . $form_state['values']['voc']->machine_name . '/' . $form_state['values']['double-tree-settings']['voc2_machine_name']);
  1462. }
  1463. function taxonomy_manager_form_double_tree_disable_submit($form, &$form_state) {
  1464. drupal_goto('admin/structure/taxonomy_manager/voc/' . $form_state['values']['voc']->machine_name);
  1465. }
  1466. /**
  1467. * Defines a settings form.
  1468. */
  1469. function taxonomy_manager_settings($form) {
  1470. $form['taxonomy_manager_disable_mouseover'] = array(
  1471. '#type' => 'checkbox',
  1472. '#title' => t('Disable mouse-over effect for terms (weights and direct link)'),
  1473. '#default_value' => variable_get('taxonomy_manager_disable_mouseover', 0),
  1474. '#description' => t('Disabeling this feature speeds up the Taxonomy Manager'),
  1475. );
  1476. $form['taxonomy_manager_pager_tree_page_size'] = array(
  1477. '#type' => 'select',
  1478. '#title' => t('Pager count'),
  1479. '#options' => array(25 => 25, 50 => 50, 75 => 75, 100 => 100, 150 => 150, 200 => 200, 250 => 250, 300 => 300, 400 => 400, 500 => 500, 1000 => 1000, 2500 => 2500, 5000 => 5000, 10000 => 10000),
  1480. '#default_value' => variable_get('taxonomy_manager_pager_tree_page_size', TAXONOMY_MANAGER_PAGER_TREE_PAGE_SIZE_DEFAULT),
  1481. '#description' => t('Select how many terms should be listed on one page. Huge page counts can slow down the Taxonomy Manager'),
  1482. );
  1483. return system_settings_form($form);
  1484. }
  1485. function taxonomy_manager_term_data_form_ajax_callback($form, $form_state) {
  1486. $commands = array();
  1487. $commands[] = ajax_command_insert(NULL, drupal_render($form['term_data']));
  1488. $commands[] = ajax_command_after('#term-data-close', theme('status_messages'));
  1489. // Update tree if necessary.
  1490. if (isset($form_state['values']['tree-update'])) {
  1491. if (isset($form_state['values']['tree-update']['update']) && $form_state['values']['tree-update']['update']) {
  1492. $commands[] = ajax_command_insert('#taxonomy-manager .form-item-taxonomy-manager-tree', drupal_render($form['taxonomy']['manager']['tree']));
  1493. if (isset($form['taxonomy2'])) {
  1494. $commands[] = ajax_command_insert('#taxonomy-manager .form-item-taxonomy2-manager-tree', drupal_render($form['taxonomy2']['manager']['tree']));
  1495. }
  1496. }
  1497. elseif (isset($form_state['values']['tree-update']['update-name'])) {
  1498. $selector = 'a.term-data-link-id-' . $form_state['values']['tree-update']['update-name']['tid'];
  1499. $commands[] = ajax_command_html($selector, '<span>' . check_plain($form_state['values']['tree-update']['update-name']['name']) . '</span>');
  1500. }
  1501. }
  1502. return array('#type' => 'ajax', '#commands' => $commands);
  1503. }
  1504. function taxonomy_manager_term_data_form_submit($form, &$form_state) {
  1505. $old_term = taxonomy_term_load($form_state['values']['tid']);
  1506. $term = taxonomy_form_term_submit_build_taxonomy_term($form, $form_state);
  1507. if ($term->weight != $old_term->weight) {
  1508. form_set_value(array('#parents' => array('tree-update')), array('update' => TRUE), $form_state);
  1509. }
  1510. elseif ($term->name != $old_term->name) {
  1511. form_set_value(array('#parents' => array('tree-update')), array('update-name' => array('name' => $term->name, 'tid' => $term->tid)), $form_state);
  1512. }
  1513. elseif (isset($term->language) && $term->language != $old_term->language) {
  1514. form_set_value(array('#parents' => array('tree-update')), array('update' => TRUE), $form_state);
  1515. }
  1516. taxonomy_term_save($term);
  1517. drupal_set_message(t('Updated term data'));
  1518. $form_state['rebuild'] = TRUE;
  1519. }
  1520. function taxonomy_manager_term_data_form_validate_parents_add($form, &$form_state) {
  1521. $term_data = $form_state['values'];
  1522. $term = taxonomy_term_load($term_data['tid']);
  1523. $parent_names = $term_data['parents']['op']['add'];
  1524. $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($parent_names, $term->vid, FALSE);
  1525. $error_msg = "";
  1526. if ($parent_names == "") {
  1527. form_set_error('parents][op][add', t("Parent field is required."));
  1528. }
  1529. elseif (_taxonomy_manager_check_duplicates($term->vid, $parent_names, $error_msg)) {
  1530. form_set_error('parents][op][add', t("Warning: Your input matches with multiple terms, because of duplicated term names. Please enter a unique term name or the term id with 'term-id:[tid]' (!error_msg)", array('!error_msg' => $error_msg)));
  1531. }
  1532. elseif (!taxonomy_manager_check_language($term->vid, array($term->tid), $typed_terms)) {
  1533. form_set_error('parents][op][add', t("Terms must be of the same language."));
  1534. }
  1535. else {
  1536. //validation for consistent hierarchy
  1537. $parents = array();
  1538. foreach ($typed_terms as $parent_info) {
  1539. $parents[$parent_info['tid']] = $parent_info['tid'];
  1540. }
  1541. if (!taxonomy_manager_check_circular_hierarchy(array($term->tid => $term->tid), $parents)) {
  1542. form_set_error('parents][op][add', t('Invalid parent. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.'));
  1543. }
  1544. }
  1545. }
  1546. /**
  1547. * Submit handler for adding parents for a term.
  1548. */
  1549. function taxonomy_manager_term_data_form_submit_parents_add($form, &$form_state) {
  1550. $term_data = $form_state['values'];
  1551. $term = taxonomy_term_load($term_data['tid']);
  1552. $parent_names = $term_data['parents']['op']['add'];
  1553. $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($parent_names, $term->vid, TRUE); //insert terms
  1554. if (!isset($term->parent)) {
  1555. $term->parent = array();
  1556. }
  1557. foreach ($typed_terms as $parent_info) {
  1558. $term->parent[] = $parent_info['tid'];
  1559. }
  1560. //remove root level entry
  1561. db_delete('taxonomy_term_hierarchy')
  1562. ->condition('tid', $term->tid)
  1563. ->condition('parent', 0)
  1564. ->execute();
  1565. taxonomy_term_save($term); //executes hooks and clears caches
  1566. taxonomy_manager_update_voc($term->vid, taxonomy_get_parents($term->tid)); // update hierarchy settings, if necessary
  1567. drupal_set_message(t('Updated hierarchy'));
  1568. $form_state['rebuild'] = TRUE;
  1569. form_set_value(array('#parents' => array('tree-update')), array('update' => TRUE), $form_state);
  1570. }
  1571. function taxonomy_manager_term_data_form_validate_parents_remove($form, &$form_state) {
  1572. $splits = explode('][', $form_state['triggering_element']['#name']);
  1573. if (count($splits) == 3 && is_numeric($splits[1])) {
  1574. form_set_value(array('#parents' => array('remove_parent_tid')), $splits[1], $form_state);
  1575. }
  1576. else {
  1577. form_set_error('parents', t('Invalid term selection.'));
  1578. }
  1579. }
  1580. /**
  1581. * Submit handler for removing a parent of a term.
  1582. */
  1583. function taxonomy_manager_term_data_form_submit_parents_remove($form, &$form_state) {
  1584. $term = taxonomy_term_load($form_state['values']['tid']);
  1585. $parent = $form_state['values']['remove_parent_tid'];
  1586. $parents = taxonomy_get_parents($term->tid);
  1587. if (!isset($term->parent)) {
  1588. $term->parent = array();
  1589. }
  1590. // Ensure that a term has a least parent 0.
  1591. if (count($parents) == 1) {
  1592. $term->parent[] = 0;
  1593. }
  1594. $term->parent = array_diff($term->parent, array($parent));
  1595. taxonomy_term_save($term); //executes hooks and clears caches
  1596. drupal_set_message(t("Removed parent"));
  1597. $form_state['rebuild'] = TRUE;
  1598. form_set_value(array('#parents' => array('tree-update')), array('update' => TRUE), $form_state);
  1599. }
  1600. /**
  1601. * Validation handler for adding a single translation on the term data form.
  1602. */
  1603. function taxonomy_manager_term_data_form_validate_translation_add($form, &$form_state) {
  1604. $term_data = $form_state['values'];
  1605. $term1 = taxonomy_term_load($term_data['tid']);
  1606. $input = $term_data['translations']['op']['add'];
  1607. $language = $term_data['translations']['op']['language'];
  1608. $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($term_data['translations']['op']['add'], $term1->vid, FALSE, $language);
  1609. if (empty($input) || count($typed_terms) > 1) {
  1610. form_set_error('translations][op][add', t("Please input one term with an appropriate language."));
  1611. }
  1612. elseif ($term1->language == $language) {
  1613. form_set_error('translations][op', t("Added term is of the same language."));
  1614. return;
  1615. }
  1616. elseif (!is_null(i18n_taxonomy_term_get_translation($term1, $language))) {
  1617. form_set_error('translations][op][language', t('A translation for this language already exists.'));
  1618. return;
  1619. }
  1620. elseif (count($typed_terms) == 1) {
  1621. $entry = array_shift($typed_terms);
  1622. $term2 = taxonomy_term_load($entry['tid']);
  1623. if (!is_null(i18n_taxonomy_term_get_translation($term2, $term1->language))) {
  1624. form_set_error('translations][op][add', t('A translation for this term already exists.'));
  1625. }
  1626. }
  1627. }
  1628. /**
  1629. * Submit handler for adding a single translation on the term data form.
  1630. */
  1631. function taxonomy_manager_term_data_form_submit_translation_add($form, &$form_state) {
  1632. $term_data = $form_state['values'];
  1633. $term1 = taxonomy_term_load($term_data['tid']);
  1634. $voc = taxonomy_vocabulary_load($term1->vid);
  1635. $typed_terms = taxonomy_manager_autocomplete_tags_get_tids($term_data['translations']['op']['add'], $term1->vid, TRUE, $term_data['translations']['op']['language']);
  1636. $entry = array_shift($typed_terms);
  1637. $term2 = taxonomy_term_load($entry['tid']);
  1638. taxonomy_manager_add_translation($term1, $term2, $voc);
  1639. drupal_set_message(t('The translation has been added'));
  1640. $form_state['rebuild'] = TRUE;
  1641. form_set_value(array('#parents' => array()), array('update' => TRUE), $form_state);
  1642. }
  1643. /**
  1644. * Validation handler for removing a single translation on the term data form.
  1645. */
  1646. function taxonomy_manager_term_data_form_validate_translation_remove($form, &$form_state) {
  1647. $splits = explode('][', $form_state['triggering_element']['#name']);
  1648. if (count($splits) == 3 && is_numeric($splits[1])) {
  1649. form_set_value(array('#parents' => array('remove_translation_tid')), $splits[1], $form_state);
  1650. }
  1651. else {
  1652. form_set_error('translations', t('Invalid term selection.'));
  1653. }
  1654. }
  1655. /**
  1656. * Submit handler for removing a single translation on the term data form.
  1657. */
  1658. function taxonomy_manager_term_data_form_submit_translation_remove($form, &$form_state) {
  1659. $term = taxonomy_term_load($form_state['values']['tid']);
  1660. $term_to_remove = taxonomy_term_load($form_state['values']['remove_translation_tid']);
  1661. $translation_set = i18n_translation_set_load($term->i18n_tsid);
  1662. $translation_set->remove_language($term_to_remove->language)
  1663. ->update_delete();
  1664. drupal_set_message(t("Removed term from translation."));
  1665. $form_state['rebuild'] = TRUE;
  1666. form_set_value(array('#parents' => array()), array('update' => TRUE), $form_state);
  1667. }
  1668. function taxonomy_manager_double_tree_ajax_callback($form, $form_state) {
  1669. $commands = array();
  1670. $commands[] = ajax_command_prepend(NULL, theme('status_messages'));
  1671. if ($form_state['values']['double_tree_values']['update_tree_left']) {
  1672. $commands[] = ajax_command_insert('#taxonomy-manager .form-item-taxonomy-manager-tree', drupal_render($form['taxonomy']['manager']['tree']));
  1673. }
  1674. if ($form_state['values']['double_tree_values']['update_tree_right']) {
  1675. $commands[] = ajax_command_insert('#taxonomy-manager .form-item-taxonomy2-manager-tree', drupal_render($form['taxonomy2']['manager']['tree']));
  1676. }
  1677. return array('#type' => 'ajax', '#commands' => $commands);
  1678. }
  1679. function taxonomy_manager_double_tree_move_validate($form, &$form_state) {
  1680. $values = array();
  1681. if (strpos($form_state['input']['_triggering_element_name'], 'right') !== FALSE) {
  1682. //move right
  1683. $values = array(
  1684. 'selected_parents' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms'],
  1685. 'selected_terms' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms'],
  1686. 'selected_terms_direct_parents' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms_direct_parents'],
  1687. 'left_tree_expand_terms' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms_direct_parents'],
  1688. 'right_tree_expand_terms' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms'],
  1689. );
  1690. }
  1691. else {
  1692. //move left
  1693. $values = array(
  1694. 'selected_parents' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms'],
  1695. 'selected_terms' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms'],
  1696. 'selected_terms_direct_parents' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms_direct_parents'],
  1697. 'left_tree_expand_terms' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms'],
  1698. 'right_tree_expand_terms' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms_direct_parents'],
  1699. );
  1700. }
  1701. $values['update_tree_right'] = TRUE;
  1702. $values['update_tree_left'] = TRUE;
  1703. if (!count($values['selected_terms'])) {
  1704. form_set_error('', t("No terms selected."));
  1705. }
  1706. elseif (is_array($values['selected_parents']) && count($values['selected_parents'])) {
  1707. $p_array = array();
  1708. foreach ($values['selected_parents'] as $parent) {
  1709. $p_array[$parent]['tid'] = $parent;
  1710. }
  1711. if (!taxonomy_manager_check_language($form_state['values']['voc']->vid, $values['selected_terms'], $p_array)) {
  1712. form_set_error('', t("Terms must be of the same language."));
  1713. }
  1714. elseif (!taxonomy_manager_check_circular_hierarchy($values['selected_terms'], $values['selected_parents'])) {
  1715. form_set_error('', t('Invalid parent. The resulting hierarchy would contain circles, which is not allowed. A term cannot be a parent of itself.'));
  1716. }
  1717. }
  1718. form_set_value(array('#parents' => array('double_tree_values')), $values, $form_state);
  1719. }
  1720. function taxonomy_manager_double_tree_move_submit($form, &$form_state) {
  1721. $selected_terms = $form_state['values']['double_tree_values']['selected_terms'];
  1722. $selected_parents = $form_state['values']['double_tree_values']['selected_parents'];
  1723. $selected_terms_direct_parents = $form_state['values']['double_tree_values']['selected_terms_direct_parents'];
  1724. $selected_terms_names = array();
  1725. foreach ($selected_terms as $tid) {
  1726. $selected_term = taxonomy_term_load($tid);
  1727. $selected_terms_names[] = $selected_term->name;
  1728. //reset all parents, except the direct parent in the tree
  1729. $term_parents = taxonomy_get_parents($tid);
  1730. $term_parents_array = array();
  1731. $direct_parent = isset($selected_terms_direct_parents[$tid]) ? $selected_terms_direct_parents[$tid] : 0;
  1732. foreach ($term_parents as $term_parent) {
  1733. if ($direct_parent != $term_parent->tid) {
  1734. $term_parents_array[$term_parent->tid] = $term_parent->tid;
  1735. }
  1736. }
  1737. $selected_parent_names = array();
  1738. if (count($selected_parents)) {
  1739. foreach ($selected_parents as $parent) {
  1740. $term = taxonomy_term_load($parent);
  1741. $selected_parent_names[] = $term->name;
  1742. $term_parents_array[$term->tid] = $term->tid;
  1743. }
  1744. }
  1745. if (count($term_parents_array) == 0) {
  1746. $term_parents_array[0] = 0;
  1747. }
  1748. taxonomy_manager_move($term_parents_array, array($tid), array('keep_old_parents' => FALSE));
  1749. taxonomy_manager_update_voc($form_state['values']['voc']->vid, $term_parents_array);
  1750. }
  1751. $term_names = implode(', ', $selected_terms_names);
  1752. if (count($selected_parents) == 0) {
  1753. drupal_set_message(t("Removed current parent form terms %terms.", array('%terms' => $term_names)));
  1754. }
  1755. else {
  1756. drupal_set_message(t("Terms %terms moved to parents %parents.", array('%terms' => $term_names, '%parents' => implode(', ', $selected_parent_names))));
  1757. }
  1758. $form_state['rebuild'] = TRUE;
  1759. }
  1760. function taxonomy_manager_double_tree_switch_validate($form, &$form_state) {
  1761. $values = array();
  1762. if (strpos($form_state['input']['_triggering_element_name'], 'right') !== FALSE) {
  1763. //move right
  1764. $values = array(
  1765. 'selected_parents' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms'],
  1766. 'selected_terms' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms'],
  1767. 'left_tree_expand_terms' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms_direct_parents'],
  1768. 'right_tree_expand_terms' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms'],
  1769. 'voc1' => $form_state['values']['voc']->vid,
  1770. 'voc2' => $form_state['values']['voc2']->vid,
  1771. );
  1772. }
  1773. else {
  1774. //move left
  1775. $values = array(
  1776. 'selected_parents' => $form_state['values']['taxonomy']['manager']['tree']['selected_terms'],
  1777. 'selected_terms' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms'],
  1778. 'left_tree_expand_terms' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms'],
  1779. 'right_tree_expand_terms' => $form_state['values']['taxonomy2']['manager']['tree']['selected_terms_direct_parents'],
  1780. 'voc1' => $form_state['values']['voc2']->vid,
  1781. 'voc2' => $form_state['values']['voc']->vid,
  1782. );
  1783. }
  1784. $values['update_tree_right'] = TRUE;
  1785. $values['update_tree_left'] = TRUE;
  1786. if (!count($values['selected_terms'])) {
  1787. form_set_error('', t("No terms selected."));
  1788. }
  1789. form_set_value(array('#parents' => array('double_tree_values')), $values, $form_state);
  1790. }
  1791. function taxonomy_manager_double_tree_copy_validate($form, &$form_state) {
  1792. taxonomy_manager_double_tree_switch_validate($form, $form_state);
  1793. $values = $form_state['values']['double_tree_values'];
  1794. if (strpos($form_state['input']['_triggering_element_name'], 'right') !== FALSE) {
  1795. $form_state['values']['double_tree_values']['update_tree_left'] = FALSE;
  1796. }
  1797. else {
  1798. $form_state['values']['double_tree_values']['update_tree_right'] = FALSE;
  1799. }
  1800. }
  1801. function taxonomy_manager_double_tree_copy_submit($form, &$form_state) {
  1802. $selected_terms = $form_state['values']['double_tree_values']['selected_terms'];
  1803. $selected_parents = $form_state['values']['double_tree_values']['selected_parents'];
  1804. $voc1 = $form_state['values']['double_tree_values']['voc1'];
  1805. $voc2 = $form_state['values']['double_tree_values']['voc2'];
  1806. $voc1 = taxonomy_vocabulary_load($voc1);
  1807. $voc2 = taxonomy_vocabulary_load($voc2);
  1808. $new_tids = taxonomy_manager_copy($selected_terms, $voc1->vid, $voc2->vid, $selected_parents);
  1809. if (count($new_tids)) {
  1810. $new_tid = array_pop($new_tids);
  1811. $form_state['values']['double_tree_values']['left_tree_expand_terms'] = array($new_tid);
  1812. $form_state['values']['double_tree_values']['right_tree_expand_terms'] = array($new_tid);
  1813. }
  1814. $selected_terms_names = array();
  1815. foreach ($selected_terms as $tid) {
  1816. $term = taxonomy_term_load($tid);
  1817. $selected_terms_names[] = $term->name;
  1818. }
  1819. $selected_parent_names = array();
  1820. if (count($selected_parents)) {
  1821. foreach ($selected_parents as $parent) {
  1822. $term = taxonomy_term_load($parent);
  1823. $selected_parent_names[] = $term->name;
  1824. $term_parents_array[$term->tid] = $term->tid;
  1825. }
  1826. }
  1827. $term_names = implode(', ', $selected_terms_names);
  1828. if (count($selected_parents) == 0) {
  1829. drupal_set_message(t("Copied %terms to vocabulary %voc.", array('%terms' => $term_names, '%voc' => $voc2->name)));
  1830. }
  1831. else {
  1832. drupal_set_message(t("Copied %terms to vocabulary %voc under parents %parents.", array('%terms' => $term_names, '%voc' => $voc2->name, '%parents' => implode(', ', $selected_parent_names))));
  1833. }
  1834. $form_state['rebuild'] = TRUE;
  1835. }
  1836. function taxonomy_manager_double_tree_switch_submit($form, &$form_state) {
  1837. $selected_terms = $form_state['values']['double_tree_values']['selected_terms'];
  1838. $selected_parents = $form_state['values']['double_tree_values']['selected_parents'];
  1839. $voc1 = $form_state['values']['double_tree_values']['voc1'];
  1840. $voc2 = $form_state['values']['double_tree_values']['voc2'];
  1841. $voc1 = taxonomy_vocabulary_load($voc1);
  1842. $voc2 = taxonomy_vocabulary_load($voc2);
  1843. taxonomy_manager_switch($selected_terms, $voc1->vid, $voc2->vid, $selected_parents);
  1844. $selected_terms_names = array();
  1845. foreach ($selected_terms as $tid) {
  1846. $term = taxonomy_term_load($tid);
  1847. $selected_terms_names[] = $term->name;
  1848. }
  1849. $selected_parent_names = array();
  1850. if (count($selected_parents)) {
  1851. foreach ($selected_parents as $parent) {
  1852. $term = taxonomy_term_load($parent);
  1853. $selected_parent_names[] = $term->name;
  1854. $term_parents_array[$term->tid] = $term->tid;
  1855. }
  1856. }
  1857. $term_names = implode(', ', $selected_terms_names);
  1858. if (count($selected_parents) == 0) {
  1859. drupal_set_message(t("Terms %terms moved to vocabulary %voc.", array('%terms' => $term_names, '%voc' => $voc2->name)));
  1860. }
  1861. else {
  1862. drupal_set_message(t("Terms %terms moved to vocabulary %voc under parents %parents.", array('%terms' => $term_names, '%voc' => $voc2->name, '%parents' => implode(', ', $selected_parent_names))));
  1863. }
  1864. $form_state['rebuild'] = TRUE;
  1865. }
  1866. /**
  1867. * Validation handler for adding a translation.
  1868. */
  1869. function taxonomy_manager_double_tree_add_translation_validate($form, &$form_state) {
  1870. if (!module_exists('i18n_taxonomy')) {
  1871. form_set_error('', t("i18n taxonomy module is not enabled."));
  1872. return;
  1873. }
  1874. if (!count($form_state['values']['taxonomy']['manager']['tree']['selected_terms']) || !count($form_state['values']['taxonomy2']['manager']['tree']['selected_terms'])) {
  1875. form_set_error('', t("No terms selected."));
  1876. return;
  1877. }
  1878. $term1 = taxonomy_term_load(array_shift($form_state['values']['taxonomy']['manager']['tree']['selected_terms']));
  1879. $term2 = taxonomy_term_load(array_shift($form_state['values']['taxonomy2']['manager']['tree']['selected_terms']));
  1880. $voc = $form_state['values']['voc'];
  1881. if (!i18n_taxonomy_vocabulary_mode($voc->vid, I18N_MODE_TRANSLATE)) {
  1882. form_set_error('', t('This is not a multilingual vocabulary.'));
  1883. return;
  1884. }
  1885. elseif ($term1->language == $term2->language) {
  1886. form_set_error('', t("Selected terms are of the same language."));
  1887. return;
  1888. }
  1889. elseif (!is_null(i18n_taxonomy_term_get_translation($term1, $term2->language)) ||
  1890. !is_null(i18n_taxonomy_term_get_translation($term2, $term1->language))) {
  1891. form_set_error('', t('A translation for this term or language already exists.'));
  1892. return;
  1893. }
  1894. // Set the values for the submit handler.
  1895. $values = array(
  1896. 'term1' => $term1,
  1897. 'term2' => $term2,
  1898. 'voc' => $voc,
  1899. );
  1900. form_set_value(array('#parents' => array('double_tree_values')), $values, $form_state);
  1901. }
  1902. /**
  1903. * Submit handler for adding a translation.
  1904. */
  1905. function taxonomy_manager_double_tree_add_translation_submit($form, &$form_state) {
  1906. $term1 = $form_state['values']['double_tree_values']['term1'];
  1907. $term2 = $form_state['values']['double_tree_values']['term2'];
  1908. $voc = $form_state['values']['double_tree_values']['voc'];
  1909. taxonomy_manager_add_translation($term1, $term2, $voc);
  1910. drupal_set_message(t("Translation for %term2 - %term1 added.", array('%term2' => $term2->name, '%term1' => $term1->name)));
  1911. }
  1912. /**
  1913. * Helper function for adding a translation between two terms.
  1914. */
  1915. function taxonomy_manager_add_translation($term1, $term2, $voc) {
  1916. if (!module_exists('i18n_taxonomy')) {
  1917. return;
  1918. }
  1919. if (!empty($term1->i18n_tsid)) {
  1920. $translation_set = i18n_taxonomy_translation_set_load($term1->i18n_tsid);
  1921. }
  1922. else {
  1923. // No translation set yet, build a new one with the source term.
  1924. $translation_set = i18n_translation_set_create('taxonomy_term', $voc->machine_name)
  1925. ->add_item($term1);
  1926. }
  1927. $translation_set->add_item($term2)->save();
  1928. }
  1929. /**
  1930. * Duplicates a term to another voc
  1931. */
  1932. function taxonomy_manager_copy($tids, $from_voc, $to_voc, $selected_parents) {
  1933. $new_tids = array();
  1934. foreach ($tids as $tid) {
  1935. $term = taxonomy_term_load($tid);
  1936. $new_term = clone $term;
  1937. unset($new_term->tid);
  1938. $new_term->parent = count($selected_parents) ? $selected_parents : 0;
  1939. $new_term->vid = $to_voc;
  1940. // UUID integration: unset uuid on copy.
  1941. if (isset($new_term->uuid)) {
  1942. unset($new_term->uuid);
  1943. }
  1944. taxonomy_term_save($new_term);
  1945. $new_tids[] = $new_term->tid;
  1946. }
  1947. taxonomy_manager_update_voc($to_voc, $selected_parents);
  1948. taxonomy_terms_static_reset();
  1949. return $new_tids;
  1950. }
  1951. /**
  1952. * Changes vocabulary of given terms and its children
  1953. * conflicts might be possible with multi-parent terms!
  1954. */
  1955. function taxonomy_manager_switch($tids, $from_voc, $to_voc, $parents = array()) {
  1956. foreach ($tids as $tid) {
  1957. //hook to inform modules about the changes
  1958. module_invoke_all('taxonomy_manager_term', 'switch', $tid, $from_voc, $to_voc);
  1959. $children = taxonomy_get_tree($from_voc, $tid);
  1960. $terms_to_switch = array();
  1961. foreach ($children as $child) {
  1962. $terms_to_switch[] = $child->tid;
  1963. }
  1964. $terms_to_switch[] = $tid;
  1965. db_update('taxonomy_term_data')
  1966. ->fields(array('vid' => $to_voc))
  1967. ->condition('tid', $terms_to_switch, 'IN')
  1968. ->execute();
  1969. taxonomy_terms_static_reset();
  1970. //delete references to parents from the old voc
  1971. foreach ($children as $child) {
  1972. $term_parents = taxonomy_get_parents($child->tid);
  1973. foreach ($term_parents as $term_parent) {
  1974. if ($term_parent->vid != $to_voc) {
  1975. db_delete('taxonomy_term_hierarchy')
  1976. ->condition('tid', $child->tid)
  1977. ->condition('parent', $term_parent->tid)
  1978. ->execute();
  1979. }
  1980. }
  1981. }
  1982. //set parent of the selected term
  1983. if (!count($parents)) {
  1984. $parents[0] = 0;
  1985. }
  1986. taxonomy_manager_move($parents, array($tid));
  1987. taxonomy_manager_update_voc($to_voc, $parents);
  1988. }
  1989. //TODO invoke update hook!!
  1990. taxonomy_terms_static_reset();
  1991. }
  1992. /**
  1993. * checks if voc has terms
  1994. *
  1995. * @param $vid voc id
  1996. * @return true, if terms already exists, else false
  1997. */
  1998. function _taxonomy_manager_voc_is_empty($vid) {
  1999. $has_rows = (bool) db_query_range("SELECT 1 FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} h ON t.tid = h.tid WHERE vid = :vid AND h.parent = 0", 0, 1, array(':vid' => $vid))->fetchField();
  2000. return !$has_rows;
  2001. }
  2002. /**
  2003. * deletes terms from the database
  2004. * optional orphans (terms where parent get deleted) can be deleted as well
  2005. *
  2006. * (difference to taxonomy_term_delete: deletion of orphans optional)
  2007. *
  2008. * @param $tids array of term id to delete
  2009. * @param $options associative array with options
  2010. * if $options['delete_orphans'] is true, orphans get deleted
  2011. */
  2012. function taxonomy_manager_delete_terms($tids, $options = array()) {
  2013. $deleted_term = array();
  2014. $remaining_child_terms = array();
  2015. if (!is_array($tids)) array($tids);
  2016. while (count($tids) > 0) {
  2017. $orphans = array();
  2018. foreach ($tids as $tid) {
  2019. if ($children = taxonomy_get_children($tid)) {
  2020. foreach ($children as $child) {
  2021. $parents = taxonomy_get_parents($child->tid);
  2022. if ($options['delete_orphans']) {
  2023. if (count($parents) == 1) {
  2024. $orphans[$child->tid] = $child->tid;
  2025. }
  2026. else {
  2027. $remaining_child_terms[$child->tid] = $child;
  2028. }
  2029. }
  2030. else {
  2031. $remaining_child_terms[$child->tid] = $child;
  2032. db_delete('taxonomy_term_hierarchy')
  2033. ->condition('tid', $child->tid)
  2034. ->condition('parent', $tid)
  2035. ->execute();
  2036. if (count($parents) == 1) {
  2037. $is_root = (bool) db_query_range("SELECT 1 FROM {taxonomy_term_hierarchy} h WHERE h.tid = :tid AND h.parent = 0", 0, 1, array(':tid' => $child->tid))->fetchField();
  2038. if (!$is_root) {
  2039. db_insert('taxonomy_term_hierarchy')
  2040. ->fields(array('tid', 'parent'))
  2041. ->values(array('tid' => $child->tid, 'parent' => 0))
  2042. ->execute();
  2043. }
  2044. }
  2045. }
  2046. }
  2047. }
  2048. $term = taxonomy_term_load($tid);
  2049. if ($term) {
  2050. $deleted_terms[] = $term;
  2051. db_delete('taxonomy_term_data')
  2052. ->condition('tid', $tid)
  2053. ->execute();
  2054. db_delete('taxonomy_term_hierarchy')
  2055. ->condition('tid', $tid)
  2056. ->execute();
  2057. field_attach_delete('taxonomy_term', $term);
  2058. module_invoke_all('taxonomy_term_delete', $term);
  2059. // Reset cache after each deletion as it might affect parents/children information that is used later on.
  2060. taxonomy_terms_static_reset();
  2061. }
  2062. }
  2063. $tids = $orphans;
  2064. }
  2065. return array('deleted_terms' => $deleted_terms, 'remaining_child_terms' => $remaining_child_terms);
  2066. }
  2067. /**
  2068. * Moves terms in hierarchies to other parents
  2069. *
  2070. * @param $parents
  2071. * Array of parent term ids to where children can be moved.
  2072. * Array should only contain more parents if multi hierarchy is enabled.
  2073. * If array contains 0, terms get moved to root level
  2074. * @param $children
  2075. * Array of term ids to move
  2076. * @param $options
  2077. * Array of additional options for moving
  2078. * 'keep_old_parents': if true, existing parents does not get deleted (only
  2079. * possible with multi hierarchies).
  2080. */
  2081. function taxonomy_manager_move($parents, $children, $options = array()) {
  2082. if (!is_array($parents)) {
  2083. $parents = array($parents);
  2084. }
  2085. // Key parent terms array by tid, so that it is always unique.
  2086. $keyed_array = array();
  2087. foreach ($parents as $parent) {
  2088. $keyed_array[$parent] = $parent;
  2089. }
  2090. $parents = $keyed_array;
  2091. foreach ($children as $child) {
  2092. $term = taxonomy_term_load($child);
  2093. $term_parents = $parents;
  2094. if (isset($options['keep_old_parents']) && $options['keep_old_parents']) {
  2095. // Add existing parents to $term_parents array
  2096. $results = db_select('taxonomy_term_hierarchy', 'h')
  2097. ->condition('tid', $child)
  2098. ->fields('h')
  2099. ->execute();
  2100. foreach ($results as $p) {
  2101. $term_parents[$p->parent] = $p->parent;
  2102. }
  2103. }
  2104. $term->parent = $term_parents;
  2105. taxonomy_term_save($term);
  2106. }
  2107. taxonomy_terms_static_reset();
  2108. }
  2109. /**
  2110. * helper function for getting out of term ids from autocomplete fields
  2111. * non-exsiting terms get inserted autmatically
  2112. * the input gets parsed for term names, optional a term id can be directly passed with prefixing the input with 'term-id:'
  2113. *
  2114. * @param $typed_input input string of form field
  2115. * @param $vid vocabulary id
  2116. * @param $insert_new TRUE if non-existing terms should be inserted
  2117. * @param $lang define the language (optional)
  2118. * @return array of term ids
  2119. */
  2120. function taxonomy_manager_autocomplete_tags_get_tids($typed_input, $vid, $insert_new = TRUE, $lang = NULL) {
  2121. $tids = array();
  2122. $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  2123. preg_match_all($regexp, $typed_input, $matches);
  2124. $typed_terms = array_unique($matches[1]);
  2125. foreach ($typed_terms as $typed_term) {
  2126. $typed_term = str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $typed_term));
  2127. $typed_term = trim($typed_term);
  2128. if ($typed_term != "") {
  2129. if (substr($typed_term, 0, 8) == "term-id:") {
  2130. $id = substr($typed_term, 8);
  2131. $term = taxonomy_term_load($id);
  2132. if ($term->vid == $vid) {
  2133. $tids[$term->tid]['tid'] = $term->tid;
  2134. }
  2135. }
  2136. else {
  2137. $possibilities = taxonomy_get_term_by_name($typed_term);
  2138. $typed_term_tid = NULL; // tid match if any.
  2139. foreach ($possibilities as $possibility) {
  2140. if ($possibility->vid == $vid && !($lang && $lang != $possibility->language)) {
  2141. $typed_term_tid = $possibility->tid;
  2142. $tids[$typed_term_tid]['tid'] = $typed_term_tid;
  2143. }
  2144. }
  2145. if (!$typed_term_tid && $insert_new) {
  2146. // Truncate long string names that will cause database exceptions.
  2147. if (strlen($typed_term) > 255) {
  2148. $typed_term = substr($typed_term, 0, 255);
  2149. }
  2150. $edit = new stdClass;
  2151. $edit->name = $typed_term;
  2152. $edit->vid = $vid;
  2153. if (module_exists('i18n_taxonomy') && $lang != "" && i18n_taxonomy_vocabulary_mode($vid, I18N_MODE_TRANSLATE)) {
  2154. $edit->language = $lang;
  2155. }
  2156. $status = taxonomy_term_save($edit);
  2157. $typed_term_tid = $edit->tid;
  2158. $tids[$typed_term_tid]['tid'] = $typed_term_tid;
  2159. $tids[$typed_term_tid]['new'] = TRUE;
  2160. }
  2161. }
  2162. }
  2163. }
  2164. return $tids;
  2165. }
  2166. /**
  2167. * similar to taxonomy_manager_autocomplete_tags_get_tids, but used for searching terms
  2168. * takes synonyms and selected subtrees into account
  2169. *
  2170. * @param $typed_input input string of form field
  2171. * @param $vid vocabulary id
  2172. * @param $include_synonyms TRUE if search should include synonyms
  2173. * @param $parents array of parents
  2174. * @return array of term ids
  2175. */
  2176. function taxonomy_manager_autocomplete_search_terms($typed_input, $vid, $include_synonyms = FALSE, $parents = array(), $language = NULL) {
  2177. $tids = array();
  2178. if ($language != NULL && $language == "no language") {
  2179. $language = "";
  2180. }
  2181. $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
  2182. preg_match_all($regexp, $typed_input, $matches);
  2183. $typed_terms = array_unique($matches[1]);
  2184. foreach ($typed_terms as $typed_term) {
  2185. $typed_term = str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $typed_term));
  2186. $typed_term = trim($typed_term);
  2187. if ($typed_term == "") {
  2188. continue;
  2189. }
  2190. //TODO
  2191. /*if ($include_synonyms) {
  2192. if ($language != NULL) {
  2193. $search_sql = db_query("SELECT td.tid FROM {term_data} td LEFT JOIN {term_synonym} ts ON td.tid = ts.tid WHERE td.vid = %d AND (td.name = '%s' OR ts.name = '%s') AND td.language = '%s'", $vid, $typed_term, $typed_term, $language);
  2194. }
  2195. else {
  2196. $search_sql = db_query("SELECT td.tid FROM {term_data} td LEFT JOIN {term_synonym} ts ON td.tid = ts.tid WHERE td.vid = %d AND (td.name = '%s' OR ts.name = '%s')", $vid, $typed_term, $typed_term);
  2197. }
  2198. }
  2199. else {
  2200. if ($language != NULL) {
  2201. $search_sql = db_query("SELECT td.tid FROM {term_data} td WHERE td.vid = %d AND td.name = '%s' AND td.language = '%s'", $vid, $typed_term, $language);
  2202. }
  2203. else {
  2204. $search_sql = db_query("SELECT td.tid FROM {term_data} td WHERE td.vid = %d AND td.name = '%s'", $vid, $typed_term);
  2205. }
  2206. }*/
  2207. $terms = taxonomy_get_term_by_name($typed_term);
  2208. foreach ($terms as $term) {
  2209. if ($term->vid == $vid) {
  2210. $tids[] = $term->tid;
  2211. }
  2212. }
  2213. if (count($parents)) {
  2214. $filtered_tids = array();
  2215. foreach ($tids as $tid) {
  2216. $parents_all = taxonomy_get_parents_all($tid);
  2217. foreach ($parents_all as $key => $parent) {
  2218. if (in_array($parent->tid, $parents)) {
  2219. $filtered_tids[] = $tid;
  2220. break;
  2221. }
  2222. }
  2223. }
  2224. $tids = $filtered_tids;
  2225. }
  2226. }
  2227. return $tids;
  2228. }
  2229. /**
  2230. * callback for updating weights
  2231. * data send through AJAX, $_POST
  2232. * $_POST[$tid] => $weight
  2233. *
  2234. */
  2235. function taxonomy_manager_update_weights() {
  2236. $submitted_data = $_POST;
  2237. if (isset($submitted_data['form_token']) && isset($submitted_data['form_id']) && !empty($submitted_data['weights']) && is_array($submitted_data['weights'])) {
  2238. if (drupal_valid_token($submitted_data['form_token'], $submitted_data['form_id'])) {
  2239. foreach ($submitted_data['weights'] as $tid => $weight) {
  2240. if (is_numeric($tid) && is_numeric($weight)) {
  2241. $term = taxonomy_term_load($tid);
  2242. $term->weight = $weight;
  2243. taxonomy_term_save($term);
  2244. }
  2245. }
  2246. }
  2247. }
  2248. exit();
  2249. }
  2250. /**
  2251. * Submit handler for the export form.
  2252. */
  2253. function taxonomy_manager_export_form_submit($form, &$form_state) {
  2254. $voc = $form_state['values']['voc'];
  2255. $selected_tids = $selected_tids = $form_state['values']['taxonomy']['manager']['tree']['selected_terms'];
  2256. $selected_tid = count($selected_tids) ? array_pop($selected_tids) : 0;
  2257. $options = $form_state['values']['export'];
  2258. $options['depth'] = !empty($options['depth']) ? $options['depth'] : NULL;
  2259. $tree = taxonomy_manager_export_get_tree($voc->vid, $selected_tid, $options['depth'], $options['scope']);
  2260. $data = '';
  2261. if ($options['format'] == 'csv') {
  2262. $data = taxonomy_manager_export_csv($tree, $options['csv']['delimiter']);
  2263. }
  2264. elseif ($options['format'] == 'term_tree') {
  2265. $data = taxonomy_manager_export_term_tree($tree);
  2266. }
  2267. $form_state['values']['export']['data'] = $data;
  2268. $form_state['rebuild'] = TRUE;
  2269. }
  2270. /**
  2271. * Ajax handler for the export form.
  2272. */
  2273. function taxonomy_manager_export_ajax_callback($form, $form_state) {
  2274. return $form['export']['data'];
  2275. }
  2276. /**
  2277. * Generates the CVS Ouput
  2278. */
  2279. function taxonomy_manager_export_csv($tree, $delimiter = ";") {
  2280. $output = "";
  2281. foreach ($tree as $term) {
  2282. $array = array();
  2283. $array[] = '"' . $term->vid . '"';
  2284. $array[] = '"' . $term->tid . '"';
  2285. $array[] = '"' . $term->name . '"';
  2286. $array[] = '"' . $term->description . '"';
  2287. foreach ($term->parents as $parent) {
  2288. $array[] = '"' . $parent . '"';
  2289. }
  2290. $output .= implode($delimiter, $array) . "\n";
  2291. }
  2292. return $output;
  2293. }
  2294. /**
  2295. * Generates term tree export that prefixes child term with dashes.
  2296. *
  2297. * The same format can be used for importing terms (see Add button).
  2298. */
  2299. function taxonomy_manager_export_term_tree($tree) {
  2300. $output = "";
  2301. foreach ($tree as $term) {
  2302. // If a term already starts with dashes, we have to escape the name.
  2303. if (substr($term->name, 0, 1) == '-') {
  2304. $name = '"' . $term->name . '"';
  2305. }
  2306. else {
  2307. $name = $term->name;
  2308. }
  2309. $output .= str_repeat('-', $term->depth) . $name . "\n";
  2310. }
  2311. return $output;
  2312. }
  2313. /**
  2314. * Helper for loading the tree to export.
  2315. */
  2316. function taxonomy_manager_export_get_tree($vid, $selected_tid, $depth, $scope) {
  2317. $tree = array();
  2318. if ($scope == 'whole_voc') {
  2319. $tree = taxonomy_get_tree($vid, 0, $depth);
  2320. }
  2321. elseif ($scope == 'children' && $selected_tid) {
  2322. $tree = taxonomy_get_tree($vid, $selected_tid, $depth);
  2323. }
  2324. elseif ($scope == 'root_terms') {
  2325. $tree = taxonomy_get_tree($vid, 0, 1);
  2326. }
  2327. return $tree;
  2328. }
  2329. /**
  2330. * Helper function that updates the hierarchy settings of a voc
  2331. */
  2332. function taxonomy_manager_update_voc($vid, $parents = array()) {
  2333. $voc = taxonomy_vocabulary_load($vid);
  2334. if ($voc->vid == $vid) {
  2335. $current_hierarchy = count($parents);
  2336. if ($current_hierarchy > 2) {
  2337. $current_hierarchy = 2;
  2338. }
  2339. if ($current_hierarchy > $voc->hierarchy) {
  2340. $voc->hierarchy = $current_hierarchy;
  2341. taxonomy_vocabulary_save($voc);
  2342. }
  2343. }
  2344. }
  2345. /**
  2346. * Retrieve a pipe delimited string of autocomplete suggestions (+synonyms)
  2347. */
  2348. function taxonomy_manager_autocomplete_load($vid, $tags_typed = '') {
  2349. // If the request has a '/' in the search text, then the menu system will have
  2350. // split it into multiple arguments, recover the intended $tags_typed.
  2351. $args = func_get_args();
  2352. // Shift off the $field_name argument.
  2353. array_shift($args);
  2354. $tags_typed = implode('/', $args);
  2355. // The user enters a comma-separated list of tags. We only autocomplete the last tag.
  2356. $tags_typed = drupal_explode_tags($tags_typed);
  2357. $last_string = drupal_strtolower(array_pop($tags_typed));
  2358. $matches = array();
  2359. if ($last_string != '') {
  2360. $query = db_select('taxonomy_term_data', 't');
  2361. $query->addTag('translatable');
  2362. $query->addTag('term_access');
  2363. // Do not select already entered terms.
  2364. if (!empty($tags_typed)) {
  2365. $query->condition('t.name', $tags_typed, 'NOT IN');
  2366. }
  2367. // Select rows that match by term name.
  2368. $tags_return = $query
  2369. ->fields('t', array('tid', 'name'))
  2370. ->condition('t.vid', $vid)
  2371. ->condition('t.name', '%' . db_like($last_string) . '%', 'LIKE')
  2372. ->range(0, 30)
  2373. ->execute()
  2374. ->fetchAllKeyed();
  2375. $prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
  2376. $matches = array();
  2377. foreach ($tags_return as $tid => $name) {
  2378. $n = $name;
  2379. // Term names containing commas or quotes must be wrapped in quotes.
  2380. if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
  2381. $n = '"' . str_replace('"', '""', $name) . '"';
  2382. }
  2383. // Add term name to list of matches.
  2384. $matches[$prefix . $n] = check_plain($name);
  2385. }
  2386. }
  2387. drupal_json_output($matches);
  2388. }
  2389. /**
  2390. * theme function for taxonomy manager form
  2391. */
  2392. function theme_taxonomy_manager_form($variables) {
  2393. $form = $variables['form'];
  2394. $pager = theme('pager');
  2395. $tree = drupal_render($form['taxonomy']);
  2396. $term_data = drupal_render($form['term_data']);
  2397. $top = drupal_render_children($form);
  2398. $output = $top . $pager;
  2399. $output .= '<div id="taxonomy-manager" class="admin clear-block">';
  2400. $output .= '<div id="taxonomy-manager-tree-outer-div" class="left clear-block">';
  2401. $output .= $tree;
  2402. $output .= '</div>';
  2403. $output .= '<div id="taxonomy-term-data" class="right clear-block">';
  2404. $output .= $term_data;
  2405. $output .= '</div>';
  2406. $output .= '</div>';
  2407. return $output;
  2408. }
  2409. /**
  2410. * theme function for taxonomy manager form
  2411. */
  2412. function theme_taxonomy_manager_double_tree_form($variables) {
  2413. $form = $variables['form'];
  2414. $pager = theme('pager');
  2415. $tree1 = drupal_render($form['taxonomy']);
  2416. $tree2 = drupal_render($form['taxonomy2']);
  2417. $operations = drupal_render($form['double-tree']);
  2418. $term_data = drupal_render($form['term_data']);
  2419. $top = drupal_render_children($form);
  2420. $output = $top . $pager;
  2421. $output .= '<div id="taxonomy-manager" class="admin clear-block">';
  2422. $output .= '<div id="taxonomy-manager-tree-outer-div" class="left clear-block">';
  2423. $output .= $tree1;
  2424. $output .= '</div>';
  2425. $output .= '<div id="taxonomy-manager-double-tree-operations">';
  2426. $output .= $operations;
  2427. $output .= '</div>';
  2428. $output .= '<div id="taxonomy2-manager-tree-outer-div" class="left clear-block">';
  2429. $output .= $tree2;
  2430. $output .= '</div>';
  2431. $output .= '<div id="taxonomy-term-data" class="term-data-overlay">';
  2432. $output .= $term_data;
  2433. $output .= '</div>';
  2434. $output .= '</div>';
  2435. return $output;
  2436. }
  2437. /**
  2438. * themes a real button form type (no form submit)
  2439. */
  2440. function theme_no_submit_button($variables) {
  2441. $element = $variables['element'];
  2442. /* Make sure not to overwrite classes.
  2443. if (isset($element['#attributes']['class'])) {
  2444. $element['#attributes']['class'][] = 'form-'. $element['#button_type'] .' '. $element['#attributes']['class'];
  2445. }
  2446. else {
  2447. $element['#attributes']['class'][] = 'form-'. $element['#button_type'];
  2448. }*/
  2449. return '<input type="button" ' . (empty($element['#name']) ? '' : 'name="' . $element['#name'] . '" ') . 'id="' . $element['#id'] . '" value="' . check_plain($element['#value']) . '" ' . drupal_attributes($element['#attributes']) . " />\n";
  2450. }
  2451. /**
  2452. * themes a image type button
  2453. */
  2454. function theme_taxonomy_manager_image_button($element) {
  2455. //TODO still used?
  2456. //Make sure not to overwrite classes
  2457. if (isset($element['#attributes']['class'])) {
  2458. $element['#attributes']['class'] = 'form-' . $element['#button_type'] . ' ' . $element['#attributes']['class'];
  2459. }
  2460. else {
  2461. $element['#attributes']['class'] = 'form-' . $element['#button_type'];
  2462. }
  2463. // here the novelty begins: check if #button_type is normal submit button or image button
  2464. $return_string = '<input ';
  2465. if ($element['#button_type'] == 'image') {
  2466. $return_string .= 'type="image" ';
  2467. }
  2468. else {
  2469. $return_string .= 'type="submit" ';
  2470. }
  2471. $return_string .= (empty($element['#id']) ? '' : 'id="' . $element['#id'] . '" ');
  2472. $return_string .= (empty($element['#name']) ? '' : 'name="' . $element['#name'] . '" ');
  2473. $return_string .= 'value="' . check_plain($element['#value']) . '" ';
  2474. $return_string .= drupal_attributes($element['#attributes']) . " />\n";
  2475. return $return_string;
  2476. }
  2477. function theme_taxonomy_manager_term_data_extra($variables) {
  2478. $element = $variables['element'];
  2479. $rows = array();
  2480. $headers = array();
  2481. foreach (element_children($element['headers']) as $key) {
  2482. if (is_array($element['headers'][$key])) {
  2483. $headers[] = drupal_render($element['headers'][$key]);
  2484. }
  2485. }
  2486. foreach (element_children($element['data']) as $tid) {
  2487. $row = array();
  2488. foreach (element_children($element['data'][$tid]) as $key) {
  2489. if (is_array($element['data'][$tid][$key])) {
  2490. $row[] = array(
  2491. 'data' => drupal_render($element['data'][$tid][$key]) . drupal_render($element['data'][$tid][$key]['tid']),
  2492. 'class' => isset($element['data'][$tid][$key]['#row-class']) ? $element['data'][$tid][$key]['#row-class'] : '',
  2493. );
  2494. }
  2495. }
  2496. $rows[] = $row;
  2497. }
  2498. $row = array();
  2499. foreach (element_children($element['op']) as $key) {
  2500. if (is_array($element['op'][$key])) {
  2501. //$row[] = drupal_render($element['op'][$key]);
  2502. $row[] = array(
  2503. 'data' => drupal_render($element['op'][$key]),
  2504. 'class' => isset($element['op'][$key]['#row-class']) ? $element['op'][$key]['#row-class'] : '',
  2505. );
  2506. }
  2507. }
  2508. $rows[] = $row;
  2509. return theme('table', array('header' => $headers, 'rows' => $rows));
  2510. }