/json-endpoints/class.wpcom-json-api-menus-v1-1-endpoint.php

  1. <?php 
  2. abstract class WPCOM_JSON_API_Menus_Abstract_Endpoint extends WPCOM_JSON_API_Endpoint { 
  3.  
  4. protected function switch_to_blog_and_validate_user( $site ) { 
  5. $site_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $site ) ); 
  6. if ( is_wp_error( $site_id ) ) { 
  7. return $site_id; 
  8.  
  9. if ( ! current_user_can( 'edit_theme_options' ) ) { 
  10. return new WP_Error( 'unauthorised', 'User cannot edit theme options on this site.', 403 ); 
  11.  
  12. if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { 
  13. $this->load_theme_functions(); 
  14.  
  15. return $site_id; 
  16.  
  17.  
  18. protected function get_locations() { 
  19. $locations = array(); 
  20. $menus = get_registered_nav_menus(); 
  21. if ( !empty( $menus ) ) { 
  22. foreach( $menus as $name => $description ) { 
  23. $locations[] = array( 'name' => $name, 'description' => $description ); 
  24.  
  25. $locations = array_merge( $locations, WPCOM_JSON_API_Menus_Widgets::get() ); 
  26.  
  27. // Primary (first) location should have defaultState -> default,  
  28. // all other locations (including widgets) should have defaultState -> empty. 
  29. for ( $i = 0; $i < count( $locations ); $i++ ) { 
  30. $locations[ $i ]['defaultState'] = $i ? 'empty' : 'default'; 
  31. return $locations; 
  32.  
  33. protected function simplify( $data ) { 
  34. $simplifier = new WPCOM_JSON_API_Menus_Simplifier( $data ); 
  35. return $simplifier->translate(); 
  36.  
  37. protected function complexify( $data ) { 
  38. $complexifier = new WPCOM_JSON_API_Menus_Complexify( $data ); 
  39. return $complexifier->translate(); 
  40.  
  41. abstract class WPCOM_JSON_API_Menus_Translator { 
  42. protected $filter = ''; 
  43.  
  44. protected $filters = array(); 
  45.  
  46. public function __construct( $menus ) { 
  47. $this->is_single_menu = ! is_array( $menus ); 
  48. $this->menus = is_array( $menus ) ? $menus : array( $menus ); 
  49.  
  50. public function translate() { 
  51. $result = $this->menus; 
  52. foreach ( $this->filters as $f ) { 
  53. $result = call_user_func( array( $this, $f ), $result ); 
  54. if ( is_wp_error($result ) ) { 
  55. return $result; 
  56. return $this->maybe_extract( $result ); 
  57.  
  58. protected function maybe_extract( $menus ) { 
  59. return $this->is_single_menu ? $menus[0] : $menus; 
  60.  
  61. public function whitelist_and_rename_with( $object, $dict ) { 
  62. $keys = array_keys( $dict ); 
  63. $return = array(); 
  64. foreach ( (array) $object as $k => $v ) { 
  65. if ( in_array( $k, $keys ) ) { 
  66. if ( is_array( $dict[ $k ] ) ) { 
  67. settype( $v, $dict[ $k ]['type'] ); 
  68. $return[ $dict[ $k ]['name'] ] = $v; 
  69. } else { 
  70. $new_k = $dict[ $k ]; 
  71. $return[ $new_k ] = $v; 
  72. return $return; 
  73.  
  74. class WPCOM_JSON_API_Menus_Simplifier extends WPCOM_JSON_API_Menus_Translator { 
  75. protected $filter = 'wpcom_menu_api_translator_simplify'; 
  76.  
  77. protected $filters = array( 
  78. 'whitelist_and_rename_keys',  
  79. 'add_locations',  
  80. 'treeify',  
  81. 'add_widget_locations',  
  82. ); 
  83.  
  84. protected $menu_whitelist = array( 
  85. 'term_id' => array( 'name' => 'id', 'type' => 'int' ),  
  86. 'name' => array( 'name' => 'name', 'type' => 'string' ),  
  87. 'description' => array( 'name' => 'description', 'type' => 'string' ),  
  88. 'items' => array( 'name' => 'items', 'type' => 'array' ),  
  89. ); 
  90.  
  91. protected $menu_item_whitelist = array( 
  92. 'db_id' => array( 'name' => 'id', 'type' => 'int' ),  
  93. 'object_id' => array( 'name' => 'content_id', 'type' => 'int' ),  
  94. 'object' => array( 'name' => 'type', 'type' => 'string' ),  
  95. 'type' => array( 'name' => 'type_family', 'type' => 'string' ),  
  96. 'type_label' => array( 'name' => 'type_label', 'type' => 'string' ),  
  97. 'title' => array( 'name' => 'name', 'type' => 'string' ),  
  98. 'menu_order' => array( 'name' => 'order', 'type' => 'int' ),  
  99. 'menu_item_parent' => array( 'name' => 'parent', 'type' => 'int' ),  
  100. 'url' => array( 'name' => 'url', 'type' => 'string' ),  
  101. 'target' => array( 'name' => 'link_target', 'type' => 'string' ),  
  102. 'attr_title' => array( 'name' => 'link_title', 'type' => 'string' ),  
  103. 'description' => array( 'name' => 'description', 'type' => 'string' ),  
  104. 'classes' => array( 'name' => 'classes', 'type' => 'array' ),  
  105. 'xfn' => array( 'name' => 'xfn', 'type' => 'string' ),  
  106. ); 
  107.  
  108. /************************** 
  109. * Filters methods 
  110. **************************/ 
  111.  
  112. public function treeify( $menus ) { 
  113. return array_map( array( $this, 'treeify_menu' ), $menus ); 
  114.  
  115. // turn the flat item list into a tree of items 
  116. protected function treeify_menu( $menu ) { 
  117. $indexed_nodes = array(); 
  118. $tree = array(); 
  119.  
  120. foreach( $menu['items'] as &$item ) { 
  121. $indexed_nodes[ $item['id'] ] = &$item; 
  122.  
  123. foreach( $menu['items'] as &$item ) { 
  124. if ( $item['parent'] && isset( $indexed_nodes[ $item['parent'] ] ) ) { 
  125. $parent_node = &$indexed_nodes[ $item['parent'] ]; 
  126. if ( !isset( $parent_node['items'] ) ) { 
  127. $parent_node['items'] = array(); 
  128. $parent_node['items'][ $item['order'] ] = &$item; 
  129. } else { 
  130. $tree[ $item['order'] ] = &$item; 
  131. unset( $item['order'] ); 
  132. unset( $item['parent'] ); 
  133.  
  134. $menu['items'] = $tree; 
  135. $this->remove_item_keys( $menu ); 
  136. return $menu; 
  137.  
  138. // recursively ensure item lists are contiguous 
  139. protected function remove_item_keys( &$item ) { 
  140. if ( ! isset( $item['items'] ) || ! is_array( $item['items'] ) ) { 
  141. return; 
  142.  
  143.  
  144. foreach( $item['items'] as &$it ) { 
  145. $this->remove_item_keys( $it ); 
  146.  
  147. $item['items'] = array_values( $item['items'] ); 
  148.  
  149. protected function whitelist_and_rename_keys( $menus ) { 
  150. $transformed_menus = array(); 
  151.  
  152. foreach ( $menus as $menu ) { 
  153. $menu = $this->whitelist_and_rename_with( $menu, $this->menu_whitelist ); 
  154.  
  155. if ( isset( $menu['items'] ) ) { 
  156. foreach ( $menu['items'] as &$item ) { 
  157. $item = $this->whitelist_and_rename_with( $item, $this->menu_item_whitelist ); 
  158.  
  159. $transformed_menus[] = $menu; 
  160.  
  161. return $transformed_menus; 
  162.  
  163. protected function add_locations( $menus ) { 
  164. $menus_with_locations = array(); 
  165.  
  166. foreach( $menus as $menu ) { 
  167. $menu['locations'] = array_keys( get_nav_menu_locations(), $menu['id'] ); 
  168. $menus_with_locations[] = $menu; 
  169.  
  170. return $menus_with_locations; 
  171.  
  172. protected function add_widget_locations( $menus ) { 
  173. $nav_menu_widgets = WPCOM_JSON_API_Menus_Widgets::get(); 
  174.  
  175. if ( ! is_array( $nav_menu_widgets ) ) { 
  176. return $menus; 
  177.  
  178. foreach ( $menus as &$menu ) { 
  179. $widget_locations = array(); 
  180.  
  181. foreach ( $nav_menu_widgets as $key => $widget ) { 
  182. if ( is_array( $widget ) && isset( $widget['nav_menu'] ) && 
  183. $widget['nav_menu'] === $menu['id'] ) { 
  184. $widget_locations[] = 'nav_menu_widget-' . $key; 
  185. $menu['locations'] = array_merge( $menu['locations'], $widget_locations ); 
  186.  
  187. return $menus; 
  188.  
  189. class WPCOM_JSON_API_Menus_Complexify extends WPCOM_JSON_API_Menus_Translator { 
  190. protected $filter = 'wpcom_menu_api_translator_complexify'; 
  191.  
  192. protected $filters = array( 
  193. 'untreeify',  
  194. 'set_locations',  
  195. 'whitelist_and_rename_keys',  
  196. ); 
  197.  
  198. protected $menu_whitelist = array( 
  199. 'id' => 'term_id',  
  200. 'name' => 'menu-name',  
  201. 'description' => 'description',  
  202. 'items' => 'items',  
  203. ); 
  204.  
  205. protected $menu_item_whitelist = array( 
  206. 'id' => 'menu-item-db-id',  
  207. 'content_id' => 'menu-item-object-id',  
  208. 'type' => 'menu-item-object',  
  209. 'type_family' => 'menu-item-type',  
  210. 'type_label' => 'menu-item-type-label',  
  211. 'name' => 'menu-item-title',  
  212. 'order' => 'menu-item-position',  
  213. 'parent' => 'menu-item-parent-id',  
  214. 'url' => 'menu-item-url',  
  215. 'link_target' => 'menu-item-target',  
  216. 'link_title' => 'menu-item-attr-title',  
  217. 'status' => 'menu-item-status',  
  218. 'tmp_id' => 'tmp_id',  
  219. 'tmp_parent' => 'tmp_parent',  
  220. 'description' => 'menu-item-description',  
  221. 'classes' => 'menu-item-classes',  
  222. 'xfn' => 'menu-item-xfn',  
  223. ); 
  224.  
  225. /************************** 
  226. * Filters methods 
  227. **************************/ 
  228.  
  229. public function untreeify( $menus ) { 
  230. return array_map( array( $this, 'untreeify_menu' ), $menus ); 
  231.  
  232. // convert the tree of menu items to a flat list suitable for 
  233. // the nav_menu APIs 
  234. protected function untreeify_menu( $menu ) { 
  235. if ( empty( $menu['items'] ) ) { 
  236. return $menu; 
  237.  
  238. $items_list = array(); 
  239. $counter = 1; 
  240. foreach ( $menu['items'] as &$item ) { 
  241. $item[ 'parent' ] = 0; 
  242. $this->untreeify_items( $menu['items'], $items_list, $counter ); 
  243. $menu['items'] = $items_list; 
  244.  
  245. return $menu; 
  246.  
  247. /** 
  248. * Recurse the items tree adding each item to a flat list and restoring 
  249. * `order` and `parent` fields. 
  250. * 
  251. * @param array $items item tree 
  252. * @param array &$items_list output flat list of items 
  253. * @param int &$counter for creating temporary IDs 
  254. */ 
  255. protected function untreeify_items( $items, &$items_list, &$counter ) { 
  256. foreach( $items as $index => $item ) { 
  257. $item['order'] = $index + 1; 
  258.  
  259. if( ! isset( $item['id'] ) ) { 
  260. $this->set_tmp_id( $item, $counter++ ); 
  261.  
  262. if ( isset( $item['items'] ) && is_array( $item['items'] ) ) { 
  263. foreach ( $item['items'] as &$i ) { 
  264. $i['parent'] = $item['id']; 
  265. $this->untreeify_items( $item[ 'items' ], $items_list, $counter ); 
  266. unset( $item['items'] ); 
  267.  
  268. $items_list[] = $item; 
  269.  
  270. /** 
  271. * Populate `tmp_id` field for a new item, and `tmp_parent` field 
  272. * for all its children, to maintain the hierarchy. 
  273. * These fields will be used when creating 
  274. * new items with wp_update_nav_menu_item(). 
  275. */ 
  276. private function set_tmp_id( &$item, $tmp_id ) { 
  277. $item['tmp_id'] = $tmp_id; 
  278. if ( ! isset( $item['items'] ) || ! is_array( $item['items'] ) ) { 
  279. return; 
  280. foreach ( $item['items'] as &$child ) { 
  281. $child['tmp_parent'] = $tmp_id; 
  282.  
  283. protected function whitelist_and_rename_keys( $menus ) { 
  284. $transformed_menus = array(); 
  285. foreach ( $menus as $menu ) { 
  286. $menu = $this->whitelist_and_rename_with( $menu, $this->menu_whitelist ); 
  287. if ( isset( $menu['items'] ) ) { 
  288. $menu['items'] = array_map( array( $this, 'whitelist_and_rename_item_keys' ), $menu['items'] ); 
  289. $transformed_menus[] = $menu; 
  290.  
  291. return $transformed_menus; 
  292.  
  293. protected function whitelist_and_rename_item_keys( $item ) { 
  294. $item = $this->implode_array_fields( $item ); 
  295. $item = $this->whitelist_and_rename_with( $item, $this->menu_item_whitelist ); 
  296. return $item; 
  297.  
  298. // all item fields are set as strings 
  299. protected function implode_array_fields( $menu_item ) { 
  300. return array_map( array( $this, 'implode_array_field' ), $menu_item ); 
  301.  
  302. protected function implode_array_field( $field ) { 
  303. if ( is_array( $field ) ) { 
  304. return implode( ' ', $field ); 
  305. return $field; 
  306.  
  307. protected function set_locations( $menus ) { 
  308. foreach ( $menus as $menu ) { 
  309. if ( isset( $menu['locations'] ) ) { 
  310. if ( true !== $this->locations_are_valid( $menu['locations'] ) ) { 
  311. return $this->locations_are_valid( $menu['locations'] ); 
  312.  
  313. return array_map( array( $this, 'set_location' ), $menus ); 
  314.  
  315. protected function set_location( $menu ) { 
  316. $this->set_menu_at_locations( $menu['locations'], $menu['id'] ); 
  317. return $menu; 
  318.  
  319. protected function set_menu_at_locations( $locations, $menu_id ) { 
  320. $location_map = get_nav_menu_locations(); 
  321. $this->remove_menu_from_all_locations( $menu_id, $location_map ); 
  322.  
  323. if ( is_array( $locations ) ) { 
  324. foreach ( $locations as $location ) { 
  325. $location_map[ $location ] = $menu_id; 
  326.  
  327. set_theme_mod( 'nav_menu_locations', $location_map ); 
  328.  
  329. $this->set_widget_menu_at_locations( $locations, $menu_id ); 
  330.  
  331. protected function remove_menu_from_all_locations( $menu_id, &$location_map ) { 
  332. foreach ( get_nav_menu_locations() as $existing_location => $existing_menu_id) { 
  333. if ( $existing_menu_id == $menu_id ) { 
  334. unset( $location_map[$existing_location] ); 
  335.  
  336. protected function set_widget_menu_at_locations( $locations, $menu_id ) { 
  337. $nav_menu_widgets = get_option( 'widget_nav_menu' ); 
  338.  
  339. if ( ! is_array( $nav_menu_widgets ) ) { 
  340. return; 
  341.  
  342. // Remove menus from all custom menu widget locations 
  343. foreach ( $nav_menu_widgets as &$widget ) { 
  344. if ( is_array( $widget ) && $widget['nav_menu'] == $menu_id ) { 
  345. $widget['nav_menu'] = 0; 
  346.  
  347. if ( is_array( $locations ) ) { 
  348. foreach ( $locations as $location ) { 
  349. if ( preg_match( '/^nav_menu_widget-(\d+)/', $location, $matches ) ) { 
  350. if ( isset( $matches[1] ) ) { 
  351. $nav_menu_widgets[$matches[1]]['nav_menu'] = $menu_id; 
  352.  
  353. update_option( 'widget_nav_menu', $nav_menu_widgets ); 
  354.  
  355. protected function locations_are_valid( $locations ) { 
  356. if ( is_int( $locations ) ) { 
  357. if ( $locations != 0) { 
  358. return new WP_Error( 'locations-int', 'Locations int must be 0.', 400 ); 
  359. } else { 
  360. return true; 
  361. } elseif ( is_array( $locations ) ) { 
  362. foreach ( $locations as $location_name ) { 
  363. if ( ! $this->location_name_exists( $location_name ) ) { 
  364. return new WP_Error( 'locations-array',  
  365. sprintf( "Location '%s' does not exist.", $location_name ), 404 ); 
  366. return true; 
  367. return new WP_Error( 'locations', 'Locations must be array or integer.', 400 ); 
  368.  
  369. protected function location_name_exists( $location_name ) { 
  370. $widget_location_names = wp_list_pluck( WPCOM_JSON_API_Menus_Widgets::get(), 'name' ); 
  371.  
  372. if ( ! is_array( get_registered_nav_menus() ) ) { 
  373. return false; 
  374.  
  375. return array_key_exists( $location_name, get_registered_nav_menus() ) || 
  376. in_array( $location_name, $widget_location_names ); 
  377.  
  378.  
  379. class WPCOM_JSON_API_Menus_New_Menu_Endpoint extends WPCOM_JSON_API_Menus_Abstract_Endpoint { 
  380. function callback( $path = '', $site = 0 ) { 
  381. $site_id = $this->switch_to_blog_and_validate_user( $this->api->get_blog_id( $site ) ); 
  382.  
  383. if ( is_wp_error( $site_id ) ) { 
  384. return $site_id; 
  385.  
  386. $data = $this->input(); 
  387.  
  388. $id = wp_create_nav_menu( $data['name'] ); 
  389.  
  390. if ( is_wp_error( $id ) ) { 
  391. return $id; 
  392.  
  393. return array( 'id' => $id ); 
  394.  
  395. class WPCOM_JSON_API_Menus_Update_Menu_Endpoint extends WPCOM_JSON_API_Menus_Abstract_Endpoint { 
  396. function callback( $path = '', $site = 0, $menu_id = 0 ) { 
  397. $site_id = $this->switch_to_blog_and_validate_user( $this->api->get_blog_id( $site ) ); 
  398.  
  399. if ( is_wp_error( $site_id ) ) { 
  400. return $site_id; 
  401.  
  402. if ( $menu_id <= 0 ) { 
  403. return new WP_Error( 'menu-id', 'Menu ID must be greater than 0.', 400 ); 
  404.  
  405. $data = $this->input( true, false ); 
  406. $data = $this->complexify( array( $data ) ); 
  407. if ( is_wp_error( $data ) ) { 
  408. return $data; 
  409. $data = $data[0]; 
  410.  
  411. // Avoid special-case handling of an unset 'items' field in empty menus 
  412. $data['items'] = isset( $data['items'] ) ? $data['items'] : array(); 
  413.  
  414. $data = $this->create_new_items( $data, $menu_id ); 
  415.  
  416. $result = wp_update_nav_menu_object( $menu_id, array( 'menu-name' => $data['menu-name'] ) ); 
  417.  
  418. if ( is_wp_error( $result ) ) { 
  419. return $result; 
  420.  
  421. $delete_status = $this->delete_items_not_present( $menu_id, $data['items'] ); 
  422. if( is_wp_error( $delete_status ) ) { 
  423. return $delete_status; 
  424.  
  425. foreach ( $data['items'] as $item ) { 
  426. $item_id = isset( $item['menu-item-db-id'] ) ? $item['menu-item-db-id'] : 0; 
  427. $result = wp_update_nav_menu_item( $menu_id, $item_id, $item ); 
  428. if ( is_wp_error( $result ) ) { 
  429. return $result; 
  430.  
  431. $items = wp_get_nav_menu_items( $menu_id, array( 'update_post_term_cache' => false ) ); 
  432.  
  433. if ( is_wp_error( $items ) ) { 
  434. return $items; 
  435.  
  436. $menu = wp_get_nav_menu_object( $menu_id ); 
  437. $menu->items = $items; 
  438.  
  439. return array( 'menu' => $this->simplify( $menu ) ); 
  440.  
  441. /** 
  442. * New items can have a 'tmp_id', allowing them to 
  443. * be used as parent items before they have been created. 
  444. * 
  445. * This function will create items that have a 'tmp_id' set, and 
  446. * update any items with a 'tmp_parent' to use the 
  447. * newly created item as a parent. 
  448. */ 
  449. function create_new_items( $data, $menu_id ) { 
  450. $tmp_to_actual_ids = array(); 
  451. foreach ( $data['items'] as &$item ) { 
  452. if ( isset( $item['tmp_id'] ) ) { 
  453. $actual_id = wp_update_nav_menu_item( $menu_id, 0, $item ); 
  454. $tmp_to_actual_ids[ $item['tmp_id'] ] = $actual_id; 
  455. unset( $item['tmp_id'] ); 
  456. $item['menu-item-db-id'] = $actual_id; 
  457.  
  458. foreach ( $data['items'] as &$item ) { 
  459. if ( isset( $item['tmp_parent'] ) ) { 
  460. $item['menu-item-parent-id'] = $tmp_to_actual_ids[ $item['tmp_parent'] ]; 
  461. unset( $item['tmp_parent'] ); 
  462.  
  463. return $data; 
  464.  
  465. /** 
  466. * remove any existing menu items not present in the supplied array. 
  467. * returns wp_error if an item cannot be deleted. 
  468. */ 
  469. function delete_items_not_present( $menu_id, $menu_items ) { 
  470.  
  471. $existing_items = wp_get_nav_menu_items( $menu_id, array( 'update_post_term_cache' => false ) ); 
  472. if ( ! is_array( $existing_items ) ) { 
  473. return true; 
  474.  
  475. $existing_ids = wp_list_pluck( $existing_items, 'db_id' ); 
  476. $ids_to_keep = wp_list_pluck( $menu_items, 'menu-item-db-id' ); 
  477. $ids_to_remove = array_diff( $existing_ids, $ids_to_keep ); 
  478.  
  479. foreach ( $ids_to_remove as $id ) { 
  480. if ( false === wp_delete_post( $id, true ) ) { 
  481. return new WP_Error( 'menu-item',  
  482. sprintf( 'Failed to delete menu item with id: %d.', $id ), 400 ); 
  483.  
  484. return true; 
  485.  
  486. class WPCOM_JSON_API_Menus_List_Menus_Endpoint extends WPCOM_JSON_API_Menus_Abstract_Endpoint { 
  487. function callback( $path = '', $site = 0 ) { 
  488. $site_id = $this->switch_to_blog_and_validate_user( $this->api->get_blog_id( $site ) ); 
  489.  
  490. if ( is_wp_error( $site_id ) ) { 
  491. return $site_id; 
  492.  
  493. $menus = wp_get_nav_menus( array( 'orderby' => 'term_id' ) ); 
  494.  
  495. if ( is_wp_error( $menus ) ) { 
  496. return $menus; 
  497.  
  498. foreach ( $menus as $m ) { 
  499. $items = wp_get_nav_menu_items( $m->term_id, array( 'update_post_term_cache' => false ) ); 
  500. if ( is_wp_error( $items ) ) { 
  501. return $items; 
  502. $m->items = $items; 
  503.  
  504. $menus = $this->simplify( $menus ); 
  505.  
  506. if ( is_wp_error( $this->get_locations() ) ) { 
  507. return $this->get_locations(); 
  508.  
  509. return array( 'menus' => $menus, 'locations' => $this->get_locations() ); 
  510.  
  511. class WPCOM_JSON_API_Menus_Get_Menu_Endpoint extends WPCOM_JSON_API_Menus_Abstract_Endpoint { 
  512. function callback( $path = '', $site = 0, $menu_id = 0 ) { 
  513. $site_id = $this->switch_to_blog_and_validate_user( $this->api->get_blog_id( $site ) ); 
  514.  
  515. if ( is_wp_error( $site_id ) ) { 
  516. return $site_id; 
  517.  
  518. if ( $menu_id <= 0 ) { 
  519. return new WP_Error( 'menu-id', 'Menu ID must be greater than 0.', 400 ); 
  520.  
  521. $menu = get_term( $menu_id, 'nav_menu' ); 
  522.  
  523. if ( is_wp_error( $menu ) ) { 
  524. return $menu; 
  525.  
  526. $items = wp_get_nav_menu_items( $menu_id, array( 'update_post_term_cache' => false ) ); 
  527.  
  528. if ( is_wp_error( $items ) ) { 
  529. return $items; 
  530.  
  531. $menu->items = $items; 
  532.  
  533. return $this->simplify( $menu ); 
  534.  
  535. class WPCOM_JSON_API_Menus_Delete_Menu_Endpoint extends WPCOM_JSON_API_Menus_Abstract_Endpoint { 
  536. function callback( $path = '', $site = 0, $menu_id = 0 ) { 
  537. $site_id = $this->switch_to_blog_and_validate_user( $this->api->get_blog_id( $site ) ); 
  538.  
  539. if ( is_wp_error( $site_id ) ) { 
  540. return $site_id; 
  541.  
  542. if ( $menu_id <= 0 ) { 
  543. return new WP_Error( 'menu-id', 'Menu ID must be greater than 0.', 400 ); 
  544.  
  545. $result = wp_delete_nav_menu( $menu_id ); 
  546. if ( ! is_wp_error( $result ) ) { 
  547. $result = array( 'deleted' => $result ); 
  548.  
  549. return $result; 
  550.  
  551. class WPCOM_JSON_API_Menus_Widgets { 
  552. static function get() { 
  553. $locations = array(); 
  554. $nav_menu_widgets = get_option( 'widget_nav_menu' ); 
  555.  
  556. if ( ! is_array( $nav_menu_widgets ) ) { 
  557. return $locations; 
  558.  
  559. foreach ( $nav_menu_widgets as $k => $v ) { 
  560. if ( is_array( $v ) && isset( $v['title'] ) ) { 
  561. $locations[$k] = array( 'name' => 'nav_menu_widget-' . $k, 'description' => $v['title'] ); 
  562.  
  563. return $locations; 
.