angular-yii2-model
Version:
Yii2 RESTful API mapper for AngularJS 1.x
1 lines • 8.38 kB
JavaScript
!function(){"use strict";function YiiModel(){function BaseModel(route){if("string"!=typeof route)throw new Error("route name is missing");var _expand,_fields,_headers,_route=route;Object.defineProperty(this,"$route",{get:function(){return _route}}),Object.defineProperty(this,"$expand",{get:function(){return _expand},set:function(value){_expand=angular.isArray(value)?value.join():value}}),Object.defineProperty(this,"$fields",{get:function(){return _fields},set:function(value){_fields=angular.isArray(value)?value.join():value}}),Object.defineProperty(this,"$baseUrl",{get:function(){return config.baseUrl+"/"+this.$route}}),Object.defineProperty(this,"$headers",{get:function(){return _headers},set:function(obj){if(_isPlainObject(obj)===!1)throw new Error("input should be contained inside an object");_headers=obj}})}function Collection(route){BaseModel.call(this,route),this.$data=[],this.$meta={};var _perPage=20,_page=1,_links={},_filters={};Object.defineProperty(this,"$perPage",{get:function(){return _perPage},set:function(value){_perPage=value}}),Object.defineProperty(this,"$page",{get:function(){return _page},set:function(value){_page=value}}),Object.defineProperty(this,"$links",{get:function(){return _links},set:function(obj){if(_isPlainObject(obj)===!1||"undefined"==typeof obj.self)throw new Error("unexpected structure for the navigation links parsed from the response headers");_links=obj}}),Object.defineProperty(this,"$filters",{get:function(){return _filters},set:function(obj){if(_isPlainObject(obj)===!1)throw new Error("input should be contained in an object");_filters=obj}}),Object.defineProperty(this,"$params",{get:function(){return angular.extend({"per-page":this.$perPage,page:this.$page,expand:this.$expand,fields:this.$fields},this.$filters)}})}function Resource(route){BaseModel.call(this,route);var _primaryKey="id",_fromServer=!1,_errors={};Object.defineProperty(this,"$primaryKey",{get:function(){return _primaryKey},set:function(value){_primaryKey=value}}),Object.defineProperty(this,"$fromServer",{get:function(){return _fromServer},set:function(value){_fromServer=value}}),Object.defineProperty(this,"$errors",{get:function(){return _errors},set:function(value){_errors=value}})}function provider(_$http_){return config=this,$http=_$http_,{all:function(route){return new Collection(route)},one:function(route){return new Resource(route)}}}var $http,config;this.baseUrl="",this.totalCountHeader="X-Pagination-Total-Count",this.pageCountHeader="X-Pagination-Page-Count",this.currentPageHeader="X-Pagination-Current-Page",this.perPageHeader="X-Pagination-Per-Page",BaseModel.prototype={$select:function(fields){this.$fields=fields},$with:function(resource){this.$expand=resource},$setHeaders:function(config){this.$headers=config}},Collection.prototype=Object.create(BaseModel.prototype),Collection.prototype.constructor=Collection,angular.extend(Collection.prototype,{$load:function(perPage){var $this=this;return perPage&&(this.$perPage=perPage),$http({url:this.$baseUrl,method:"GET",params:this.$params,headers:this.$headers}).then(function(response){return _responseParser.call($this,response),$this})},$isFirst:function(){return 1===this.$meta.currentPage},$isLast:function(){return this.$meta.currentPage===this.$meta.pageCount},$existNext:function(){return"undefined"!=typeof this.$links.next},$existPrev:function(){return"undefined"!=typeof this.$links.prev},$firstPage:function(){return this.$isFirst()!==!0?_getByUrl.call(this,this.$links.first):void 0},$nextPage:function(){return this.$existNext()!==!1?_getByUrl.call(this,this.$links.next):void 0},$prevPage:function(){return this.$existPrev()!==!1?_getByUrl.call(this,this.$links.prev):void 0},$lastPage:function(){return this.$isLast()!==!0?_getByUrl.call(this,this.$links.last):void 0},$getPage:function(pageNumber){return pageNumber===this.$meta.currentPage||pageNumber>this.$meta.totalCount?void 0:(this.$page=pageNumber,this.$load())},$refresh:function(){return _getByUrl.call(this,this.$links.self)},$where:function(params){return this.$filters=params,this.$load()}}),Resource.prototype=Object.create(BaseModel.prototype),Resource.prototype.constructor=Resource,angular.extend(Resource.prototype,{$setData:function(item){angular.extend(this,item)},$find:function(id){if("undefined"==typeof id)throw new Error("item id is required");var $this=this;return $http({url:this.$baseUrl+"/"+id,method:"GET",params:{expand:this.$expand,fields:this.$fields},headers:this.$headers}).then(function(response){return $this.$setData(response.data),$this.$fromServer=!0,$this})},$getPrimaryKey:function(){return this[this.$primaryKey]},$isNew:function(){return this.$fromServer===!1||"undefined"==typeof this.$getPrimaryKey()},$hasErrors:function(){if(this.$errors.constructor!==Object)throw new Error("$errors is expected to be an object");return 0!==Object.keys(this.$errors).length},$clearErrors:function(){this.$hasErrors()===!0&&(this.$errors={})},$update:function(){if(this.$isNew())throw new Error("item should be first saved");this.$clearErrors();var $this=this;return $http({url:this.$baseUrl+"/"+this.$getPrimaryKey(),method:"PUT",params:{expand:this.$expand,fields:this.$fields},headers:this.$headers,data:this}).then(function(response){return $this.$setData(response.data),$this},function(error){422===error.status&&angular.forEach(error.data,function(e){var errObj={message:e.message,pattern:"(?!^"+_preg_quote($this[e.field])+"$)(^.*$)"};$this.$errors[e.field]=errObj})})},$create:function(){this.$clearErrors();var $this=this;return $http({url:this.$baseUrl,method:"POST",params:{expand:this.$expand,fields:this.$fields},headers:this.$headers,data:this}).then(function(response){return $this.$setData(response.data),$this.$fromServer=!0,$this},function(error){422===error.status&&angular.forEach(error.data,function(e){var errObj={message:e.message,pattern:"(?!^"+_preg_quote($this[e.field])+"$)(^.*$)"};$this.$errors[e.field]=errObj})})},$save:function(){return this.$isNew()?this.$create():this.$update()},$delete:function(){if(this.$isNew())throw new Error("item is not yet saved");var $this=this;return $http({url:this.$baseUrl+"/"+this.$getPrimaryKey(),method:"DELETE",headers:this.$headers}).then(function(){return $this.$fromServer=!1,$this})}});var _isPlainObject=function(obj){if("object"==typeof obj&&null!==obj){if("function"==typeof Object.getPrototypeOf){var proto=Object.getPrototypeOf(obj);return proto===Object.prototype||null===proto}return"[object Object]"==Object.prototype.toString.call(obj)}return!1},_parse_link_header=function(header){for(var links={},parts=header.split(","),i=0;i<parts.length;i++){var section=parts[i].split(";");if(2!=section.length)throw new Error("section could not be split on ';'");var url=section[0].replace(/<(.*)>/,"$1").trim(),name=section[1].replace(/rel=(.*)/,"$1").trim();links[name]=decodeURIComponent(url)}return links},_parse_url_params=function(url){for(var params={},parts=url.slice(url.indexOf("?")+1).split("&"),i=0;i<parts.length;i++){var query=parts[i].split("=");params[query[0]]=query[1]}return params},_preg_quote=function(str,delimiter){return(str+"").replace(new RegExp("[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\"+(delimiter||"")+"-]","g"),"\\$&")},_getByUrl=function(url){var $this=this;return $http.get(url,{headers:this.$headers}).then(function(response){return _responseParser.call($this,response),$this})},_responseParser=function(response){this.$data=response.data,this.$meta.currentPage=+response.headers(config.currentPageHeader),this.$meta.pageCount=+response.headers(config.pageCountHeader),this.$meta.perPage=+response.headers(config.perPageHeader),this.$meta.totalCount=+response.headers(config.totalCountHeader);var headerLink=response.headers("Link");if(null===headerLink||0===headerLink.length)throw new Error("Enable to parse headers. Be sure 'baseUrl' to Yii server is correct and the 'Link' header is exposed to the browser as shown in this extension's README.md file.");if(this.$links=_parse_link_header(headerLink),this.$links.self){var params=_parse_url_params(this.$links.self);params.perPage&&(this.$perPage=+params.perPage),params.page&&(this.$page=+params.page),params.expand&&(this.$expand=params.expand),params.fields&&(this.$fields=params.fields)}};this.$get=provider,provider.$inject=["$http"]}angular.module("angular-yii2-model",[]).provider("YiiModel",YiiModel),YiiModel.$inject=[]}();